Code

Added default for session lifetime
[gosa.git] / gosa-si / gosa-si-server
index 510a049cf6676c476d66882bab197c841742da0d..1e56d7ce7066ed3b9cdf0f9ae743cc7880d81eb5 100755 (executable)
@@ -1,9 +1,9 @@
 #!/usr/bin/perl
 #===============================================================================
 #
-#         FILE:  gosa-sd
+#         FILE:  gosa-si-server
 #
-#        USAGE:  ./gosa-sd
+#        USAGE:  ./gosa-si-server
 #
 #  DESCRIPTION:
 #
@@ -20,8 +20,6 @@
 #     REVISION:  ---
 #===============================================================================
 
-my $server_version = '$HeadURL: https://oss.gonicus.de/repositories/gosa/trunk/gosa-si/gosa-si-server $:$Rev$';
-
 use strict;
 use warnings;
 use Getopt::Long;
@@ -39,7 +37,7 @@ use Digest::MD5  qw(md5 md5_hex md5_base64);
 use XML::Simple;
 use Data::Dumper;
 use Sys::Syslog qw( :DEFAULT setlogsock);
-use Time::HiRes qw( usleep);
+use Time::HiRes qw( usleep clock_gettime );
 use Cwd;
 use File::Spec;
 use File::Basename;
@@ -50,21 +48,21 @@ use GOSA::GosaSupportDaemon;
 use POE qw(Component::Server::TCP Wheel::Run Filter::Reference);
 use Net::LDAP;
 use Net::LDAP::Util qw(:escape);
-use ResourcePool;
-use ResourcePool::Factory::Net::LDAP;
+
+my $server_version = '$HeadURL: https://oss.gonicus.de/repositories/gosa/trunk/gosa-si/gosa-si-server $:$Rev$';
 
 # revision number of server and program name
 my $server_headURL;
 my $server_revision;
 my $server_status;
 our $prg= basename($0);
+our $verbose= 0;
 
 my $db_module = "DBsqlite";
 {
 no strict "refs";
 require ("GOSA/".$db_module.".pm");
 ("GOSA/".$db_module)->import;
-daemon_log("0 INFO: importing database module '$db_module'", 1);
 }
 
 my $modules_path = "/usr/lib/gosa-si/modules";
@@ -76,7 +74,9 @@ my ($server);
 my ($gosa_server, $job_queue_timeout, $job_queue_loop_delay);
 my ($messaging_db_loop_delay);
 my ($procid, $pid);
-my ($arp_fifo, $ldap_pool, $ldap_factory);
+my $arp_fifo;
+my $debug_parts = 0;
+my $debug_parts_bitstring;
 my ($xml);
 my $sources_list;
 my $max_clients;
@@ -89,11 +89,12 @@ our (%cfg_defaults, $log_file, $pid_file,
     $server_ip, $server_port, $ClientPackages_key, $dns_lookup,
     $arp_activ, $gosa_unit_tag,
     $GosaPackages_key, $gosa_timeout,
-    $foreign_server_string, $server_domain, $ServerPackages_key, $foreign_servers_register_delay,
+    $serverPackages_enabled, $foreign_server_string, $server_domain, $ServerPackages_key, $foreign_servers_register_delay,
     $wake_on_lan_passwd, $job_synchronization, $modified_jobs_loop_delay,
     $arp_enabled, $arp_interface,
     $opsi_enabled, $opsi_server, $opsi_admin, $opsi_password,
-               $new_systems_ou,
+    $new_systems_ou,
+    $arch,
 );
 
 # additional variable which should be globaly accessable
@@ -101,19 +102,15 @@ our $server_address;
 our $server_mac_address;
 our $gosa_address;
 our $no_arp;
-our $verbose;
 our $forground;
 our $cfg_file;
-our ($ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password, $ldap_server_dn, $ldap_version, $max_ldap_handle, $precreate_ldap_handle);
+our ($ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password, $ldap_server_dn, $ldap_version, $ldap_retry_sec);
 our ($mysql_username, $mysql_password, $mysql_database, $mysql_host);
 our $known_modules;
+our $known_functions;
 our $root_uid;
 our $adm_gid;
 
-
-# specifies the verbosity of the daemon_log
-$verbose = 0 ;
-
 # if foreground is not null, script will be not forked to background
 $foreground = 0 ;
 
@@ -154,13 +151,14 @@ my @job_queue_col_names = ("id INTEGER PRIMARY KEY",
        "plainname VARCHAR(255) DEFAULT 'none'",
        "siserver VARCHAR(255) DEFAULT 'none'",
        "modified INTEGER DEFAULT '0'",
+       "periodic VARCHAR(6) DEFAULT 'none'",
 );
 
 # holds all other gosa-si-server
 our $known_server_db;
 our $known_server_tn = "known_server";
 my $known_server_file_name;
-my @known_server_col_names = ("hostname VARCHAR(255)", "macaddress VARCHAR(17)", "status VARCHAR(255)", "hostkey VARCHAR(255)", "loaded_modules TEXT", "timestamp VARCHAR(14)");
+my @known_server_col_names = ("hostname VARCHAR(255)", "macaddress VARCHAR(17)", "status VARCHAR(255)", "hostkey VARCHAR(255)", "loaded_modules TEXT", "timestamp VARCHAR(14)", "update_time VARCHAR(14)");
 
 # holds all registrated clients
 our $known_clients_db;
@@ -197,7 +195,6 @@ our $packages_list_tn = "packages_list";
 my $packages_list_file_name;
 our @packages_list_col_names = ("distribution VARCHAR(255)", "package VARCHAR(255)", "version VARCHAR(255)", "section VARCHAR(255)", "description TEXT", "template LONGBLOB", "timestamp VARCHAR(14)");
 my $outdir = "/tmp/packages_list_db";
-my $arch = "i386"; 
 
 # holds all messages which should be delivered to a user
 our $messaging_db;
@@ -225,6 +222,12 @@ our $opsi_url;
 # of this, the user is deleted from login_users_db
 our $logged_in_user_date_of_expiry = 600;
 
+# List of month names, used in function daemon_log
+my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+
+# List of accepted periodical xml tags related to cpan modul DateTime
+our $check_periodic = {"months"=>'', "weeks"=>'', "days"=>'', "hours"=>'', "minutes"=>''};
+
 
 %cfg_defaults = (
 "general" => {
@@ -244,44 +247,45 @@ our $logged_in_user_date_of_expiry = 600;
     "messaging"             => [\$messaging_file_name, '/var/lib/gosa-si/messaging.db'],
     "foreign-clients"       => [\$foreign_clients_file_name, '/var/lib/gosa-si/foreign_clients.db'],
     "source-list"           => [\$sources_list, '/etc/apt/sources.list'],
-    "repo-path"             => [\$repo_path, '/srv/www/repository'],
+    "repo-path"             => [\$repo_path, '/srv/www'],
+    "debian-arch"           => [\$arch, 'i386'],     
     "ldap-uri"              => [\$ldap_uri, ""],
     "ldap-base"             => [\$ldap_base, ""],
     "ldap-admin-dn"         => [\$ldap_admin_dn, ""],
     "ldap-admin-password"   => [\$ldap_admin_password, ""],
-       "ldap-version"                  => [\$ldap_version, 3],
-       "max-ldap-handle"               => [\$max_ldap_handle, 10],
-       "precreate-ldap-handle" => [\$precreate_ldap_handle, 5],
+    "ldap-version"          => [\$ldap_version, 3],
+    "ldap-retry-sec"        => [\$ldap_retry_sec, 10],
     "gosa-unit-tag"         => [\$gosa_unit_tag, ""],
     "max-clients"           => [\$max_clients, 10],
     "wol-password"          => [\$wake_on_lan_passwd, ""],
-       "mysql-username"        => [\$mysql_username, "gosa_si"],
-       "mysql-password"        => [\$mysql_password, ""],
-       "mysql-database"        => [\$mysql_database, "gosa_si"],
-       "mysql-host"            => [\$mysql_host, "127.0.0.1"],
+    "mysql-username"        => [\$mysql_username, "gosa_si"],
+    "mysql-password"        => [\$mysql_password, ""],
+    "mysql-database"        => [\$mysql_database, "gosa_si"],
+    "mysql-host"            => [\$mysql_host, "127.0.0.1"],
     },
 "GOsaPackages" => {
     "job-queue" => [\$job_queue_file_name, '/var/lib/gosa-si/jobs.db'],
     "job-queue-loop-delay" => [\$job_queue_loop_delay, 3],
     "messaging-db-loop-delay" => [\$messaging_db_loop_delay, 3],
     "key" => [\$GosaPackages_key, "none"],
-               "new-systems-ou" => [\$new_systems_ou, 'ou=workstations,ou=systems'],
+    "new-systems-ou" => [\$new_systems_ou, 'ou=workstations,ou=systems'],
     },
 "ClientPackages" => {
     "key" => [\$ClientPackages_key, "none"],
     "user-date-of-expiry" => [\$logged_in_user_date_of_expiry, 600],
     },
 "ServerPackages"=> {
+    "enabled"      => [\$serverPackages_enabled, "true"],
     "address"      => [\$foreign_server_string, ""],
-    "dns-lookup"            => [\$dns_lookup, "true"],
-    "domain"  => [\$server_domain, ""],
-    "key"     => [\$ServerPackages_key, "none"],
+    "dns-lookup"   => [\$dns_lookup, "true"],
+    "domain"       => [\$server_domain, ""],
+    "key"          => [\$ServerPackages_key, "none"],
     "key-lifetime" => [\$foreign_servers_register_delay, 120],
     "job-synchronization-enabled" => [\$job_synchronization, "true"],
     "synchronization-loop" => [\$modified_jobs_loop_delay, 5],
     },
 "ArpHandler" => {
-    "enabled"   => [\$arp_enabled, "true"],
+    "enabled"   => [\$arp_enabled, "false"],
     "interface" => [\$arp_interface, "all"],
        },
 "Opsi" => {
@@ -302,16 +306,30 @@ our $logged_in_user_date_of_expiry = 600;
 #===============================================================================
 sub usage {
     print STDERR << "EOF" ;
-usage: $prg [-hvf] [-c config]
+usage: $prg [-hvf] [-c config] [-d number]
 
            -h        : this (help) message
            -c <file> : config file
            -f        : foreground, process will not be forked to background
            -v        : be verbose (multiple to increase verbosity)
+                              'v': error logs
+                            'vvv': warning plus error logs                                             
+                          'vvvvv': info plus warning logs
+                        'vvvvvvv': debug plus info logs
            -no-arp   : starts $prg without connection to arp module
+           -d <int>  : if verbose level is higher than 7x 'v' specified parts can be debugged
+                           1 : report incoming messages
+                           2 : report unencrypted outgoing messages 
+                           4 : report encrypting key for messages
+                           8 : report decrypted incoming message and verification if the message complies gosa-si requirements
+                          16 : message processing
+                          32 : ldap connectivity
+                          64 : database status and connectivity
+                         128 : main process 
+                         256 : creation of packages_list_db
+                         512 : ARP debug information
 EOF
-    print "\n" ;
+       exit(0);
 }
 
 
@@ -324,48 +342,69 @@ EOF
 #  DESCRIPTION:  function for logging
 #===============================================================================
 sub daemon_log {
-    # log into log_file
     my( $msg, $level ) = @_;
-    if(not defined $msg) { return }
-    if(not defined $level) { $level = 1 }
-               if($level > $verbose) { return }
-    if(defined $log_file){
-        my $open_log_fh = sysopen(LOG_HANDLE, $log_file, O_WRONLY | O_CREAT | O_APPEND , 0440);
-        if(not $open_log_fh) {
-            print STDERR "cannot open $log_file: $!";
-            return;
-        }
-        # check owner and group of log_file and update settings if necessary
-        my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($log_file);
-        if((not $uid eq $root_uid) || (not $gid eq $adm_gid)) {
-            chown($root_uid, $adm_gid, $log_file);
+    if (not defined $msg) { return }
+    if (not defined $level) { $level = 1 }
+       my $to_be_logged = 0;
+
+       # Write log line if line level is lower than verbosity given in commandline
+       if ($level <= $verbose) 
+       { 
+               $to_be_logged = 1 ;
+       }
+
+       # Write if debug flag is set and bitstring matches
+       if ($debug_parts > 0)
+       {
+               my $tmp_level = ($level - 10 >= 0) ? $level - 10 : 0 ;
+               my $tmp_level_bitstring = unpack("B32", pack("N", $tmp_level));
+               if (int($debug_parts_bitstring & $tmp_level_bitstring)) 
+               {
+                       $to_be_logged = 1;
                }
+       }
 
-        chomp($msg);
-        #$msg =~s/\n//g;   # no newlines are allowed in log messages, this is important for later log parsing
-        if($level <= $verbose){
-            my ($seconds, $minutes, $hours, $monthday, $month,
-                    $year, $weekday, $yearday, $sommertime) = localtime(time);
-            $hours = $hours < 10 ? $hours = "0".$hours : $hours;
-            $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes;
-            $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds;
-            my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
-            $month = $monthnames[$month];
-            $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
-            $year+=1900;
-            my $name = $prg;
-
-            my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n";
+       if ($to_be_logged) 
+       {
+               if(defined $log_file){
+                       my $open_log_fh = sysopen(LOG_HANDLE, $log_file, O_WRONLY | O_CREAT | O_APPEND , 0440);
+                       if(not $open_log_fh) {
+                               print STDERR "cannot open $log_file: $!";
+                               return;
+                       }
+                       # Check owner and group of log_file and update settings if necessary
+                       my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($log_file);
+                       if((not $uid eq $root_uid) || (not $gid eq $adm_gid)) {
+                               chown($root_uid, $adm_gid, $log_file);
+                       }
+
+                       # Prepare time string for log message
+                       my ($seconds,$minutes,$hours,$monthday,$month,$year,$weekday,$yearday,$sommertime) = localtime(time);
+                       $hours = $hours < 10 ? $hours = "0".$hours : $hours;
+                       $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes;
+                       $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds;
+                       $month = $monthnames[$month];
+                       $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday;
+                       $year+=1900;
+
+                       # Microseconds since epoch
+                       my $microSeconds = sprintf("%.2f", &Time::HiRes::clock_gettime());
+                       $microSeconds =~ s/^\d*(.\d\d)$/$1/;
+
+                       # Build log message and write it to log file and commandline
+                       chomp($msg);
+                       my $log_msg = "$month $monthday $hours:$minutes:$seconds$microSeconds $prg $msg\n";
                        flock(LOG_HANDLE, LOCK_EX);
                        seek(LOG_HANDLE, 0, 2);
-            print LOG_HANDLE $log_msg;
+                       print LOG_HANDLE $log_msg;
                        flock(LOG_HANDLE, LOCK_UN);
-            if( $foreground ) { 
-                print STDERR $log_msg;
-            }
-        }
-        close( LOG_HANDLE );
-    }
+                       if( $foreground ) 
+                       { 
+                               print STDERR $log_msg;
+                       }
+                       close( LOG_HANDLE );
+               }
+       }
 }
 
 
@@ -376,21 +415,33 @@ sub daemon_log {
 #  DESCRIPTION:  validates commandline parameter
 #===============================================================================
 sub check_cmdline_param () {
-    my $err_config;
     my $err_counter = 0;
+
+       # Check configuration file
        if(not defined($cfg_file)) {
                $cfg_file = "/etc/gosa-si/server.conf";
                if(! -r $cfg_file) {
-                       $err_config = "please specify a config file";
-                       $err_counter += 1;
+                       print STDERR "Please specify a config file.\n";
+                       $err_counter++;
                }
     }
-    if( $err_counter > 0 ) {
-        &usage( "", 1 );
-        if( defined( $err_config)) { print STDERR "$err_config\n"}
-        print STDERR "\n";
-        exit( -1 );
-    }
+
+       # Prepare identification which gosa-si parts should be debugged and which not
+       if (defined $debug_parts) 
+       {
+               if ($debug_parts =~ /^\d+$/)
+               {
+                       $debug_parts_bitstring = unpack("B32", pack("N", $debug_parts));
+               }
+               else
+               {
+                       print STDERR "Value '$debug_parts' invalid for option d (number expected)\n";
+                       $err_counter++;
+               }
+       }
+
+       # Exit if an error occour
+    if( $err_counter > 0 ) { &usage( "", 1 ); }
 }
 
 
@@ -403,28 +454,28 @@ sub check_cmdline_param () {
 sub check_pid {
     $pid = -1;
     # Check, if we are already running
-    if( open(LOCK_FILE, "<$pid_file") ) {
-        $pid = <LOCK_FILE>;
+    if( open( my $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( $stat ) {
                                        print STDERR "\nERROR: Already running!\n";
-                    close( LOCK_FILE );
+                    close( $LOCK_FILE );
                     exit -1;
                 }
             }
         }
-        close( LOCK_FILE );
+        close( $LOCK_FILE );
         unlink( $pid_file );
     }
 
     # create a syslog msg if it is not to possible to open PID file
-    if (not sysopen(LOCK_FILE, $pid_file, O_WRONLY|O_CREAT|O_EXCL, 0644)) {
+    if (not sysopen(my $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>))
+        if (open(my $LOCK_FILE, '<', $pid_file)
+                && ($pid = <$LOCK_FILE>))
         {
             chomp($pid);
             $msg .= "(PID $pid)\n";
@@ -452,15 +503,12 @@ sub check_pid {
 #                state is on is imported by "require 'file';"
 #===============================================================================
 sub import_modules {
-    daemon_log(" ", 1);
-
     if (not -e $modules_path) {
         daemon_log("0 ERROR: cannot find directory or directory is not readable: $modules_path", 1);   
     }
 
     opendir (DIR, $modules_path) or die "ERROR while loading modules from directory $modules_path : $!\n";
 
-       my $ldap_handle = &get_ldap_handle;
     while (defined (my $file = readdir (DIR))) {
         if (not $file =~ /(\S*?).pm$/) {
             next;
@@ -471,6 +519,13 @@ sub import_modules {
         if( $file =~ /ArpHandler.pm/ ) {
             if( $arp_enabled eq "false" ) { next; }
         }
+
+               # ServerPackages switch
+               if ($file eq "ServerPackages.pm" && $serverPackages_enabled eq "false") 
+               {
+                       $dns_lookup = "false";
+                       next; 
+               }
         
         eval { require $file; };
         if ($@) {
@@ -478,7 +533,7 @@ sub import_modules {
             daemon_log("$@", 1);
            exit;
                } else {
-                       my $info = eval($mod_name.'::get_module_info($ldap_handle)');
+                       my $info = eval($mod_name.'::get_module_info()');
                        # Only load module if get_module_info() returns a non-null object
                        if( $info ) {
                                my ($input_address, $input_key, $event_hash) = @{$info};
@@ -487,7 +542,6 @@ sub import_modules {
                        }
                }
     }   
-       &release_ldap_handle($ldap_handle); 
     close (DIR);
 }
 
@@ -548,7 +602,7 @@ sub check_key_and_xml_validity {
 
         if ($msg =~ /<xml>/i){
             $msg =~ s/\s+/ /g;  # just for better daemon_log
-            daemon_log("$session_id DEBUG: decrypted_msg: \n$msg", 9);
+            daemon_log("$session_id DEBUG: decrypted_msg: \n$msg", 18);
             $msg_hash = $xml->XMLin($msg, ForceArray=>1);
 
             ##############
@@ -615,15 +669,17 @@ sub check_outgoing_xml_validity {
             die 'source has length 0';
         }
 
-                               # Check if source contains hostname instead of ip address
-                               if($source =~ /^[a-z][a-z0-9\.]+:\d+$/i) {
-                                               my ($hostname,$port) = split(/:/, $source);
-                                               my $ip_address = inet_ntoa(scalar gethostbyname($hostname));
-                                               if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $port =~ /^\d+$/) {
-                                                       # Write ip address to $source variable
-                                                       $source = "$ip_address:$port";
-                                               }
-                               }
+               # Check if source contains hostname instead of ip address
+               if($source =~ /^[a-z][\w\-\.]+:\d+$/i) {
+                       my ($hostname,$port) = split(/:/, $source);
+                       my $ip_address = inet_ntoa(scalar gethostbyname($hostname));
+                       if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $port =~ /^\d+$/) {
+                               # Write ip address to $source variable
+                               $source = "$ip_address:$port";
+                               $msg_hash->{source}[0] = $source ;
+                               $msg =~ s/<source>.*<\/source>/<source>$source<\/source>/; 
+                       }
+               }
         unless( $source =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ ||
                 $source =~ /^GOSA$/i) {
             die "source '$source' is neither a complete ip-address with port nor 'GOSA'";
@@ -655,7 +711,7 @@ sub check_outgoing_xml_validity {
         $msg_hash = undef;
     }
 
-    return ($msg_hash);
+    return ($msg, $msg_hash);
 }
 
 
@@ -672,27 +728,27 @@ sub input_from_known_server {
             next;
         }
         my $host_key = $hit->{hostkey};
-        daemon_log("$session_id DEBUG: input_from_known_server: host_name: $host_name", 7);
-        daemon_log("$session_id DEBUG: input_from_known_server: host_key: $host_key", 7);
+        daemon_log("$session_id DEBUG: input_from_known_server: host_name: $host_name", 14);
+        daemon_log("$session_id DEBUG: input_from_known_server: host_key: $host_key", 14);
 
         # check if module can open msg envelope with module key
         my ($tmp_msg, $tmp_msg_hash) = &check_key_and_xml_validity($input, $host_key, $session_id);
         if( (!$tmp_msg) || (!$tmp_msg_hash) ) {
-            daemon_log("$session_id DEBUG: input_from_known_server: deciphering raise error", 7);
-            daemon_log("$@", 8);
+            daemon_log("$session_id DEBUG: input_from_known_server: deciphering raise error", 14);
+            daemon_log("$@", 14);
             next;
         }
         else {
             $msg = $tmp_msg;
             $msg_hash = $tmp_msg_hash;
             $module = "ServerPackages";
-            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 7);
+            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 14);
             last;
         }
     }
 
     if( (!$msg) || (!$msg_hash) || (!$module) ) {
-        daemon_log("$session_id DEBUG: Incoming message is not from a known server", 7);
+        daemon_log("$session_id DEBUG: Incoming message is not from a known server", 14);
     }
   
     return ($msg, $msg_hash, $module);
@@ -707,30 +763,29 @@ sub input_from_known_client {
     my $query_res = $known_clients_db->select_dbentry( $sql_statement ); 
     while( my ($hit_num, $hit) = each %{ $query_res } ) {    
         my $host_name = $hit->{hostname};
-        if( not $host_name =~ /^$remote_ip:\d*$/) {
+        if( not $host_name =~ /^$remote_ip/) {
                 next;
                }
         my $host_key = $hit->{hostkey};
-        &daemon_log("$session_id DEBUG: input_from_known_client: host_name: $host_name", 7);
-        &daemon_log("$session_id DEBUG: input_from_known_client: host_key: $host_key", 7);
+        &daemon_log("$session_id DEBUG: input_from_known_client: host_name: $host_name", 14);
+        &daemon_log("$session_id DEBUG: input_from_known_client: host_key: $host_key", 14);
 
         # check if module can open msg envelope with module key
         ($msg, $msg_hash) = &check_key_and_xml_validity($input, $host_key, $session_id);
 
         if( (!$msg) || (!$msg_hash) ) {
-            &daemon_log("$session_id DEGUG: input_from_known_client: deciphering raise error", 7);
-            &daemon_log("$@", 8);
+            &daemon_log("$session_id DEGUG: input_from_known_client: deciphering raise error", 14);
             next;
         }
         else {
             $module = "ClientPackages";
-            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 7);
+            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 14);
             last;
         }
     }
 
     if( (!$msg) || (!$msg_hash) || (!$module) ) {
-        &daemon_log("$session_id DEBUG: Incoming message is not from a known client", 7);
+        &daemon_log("$session_id DEBUG: Incoming message is not from a known client", 14);
     }
 
     return ($msg, $msg_hash, $module);
@@ -756,7 +811,7 @@ sub input_from_unknown_host {
                        daemon_log("$session_id ERROR: no key specified in config file for $mod", 1);
                        next;
                }
-               daemon_log("$session_id DEBUG: $mod: $module_key", 7);
+               daemon_log("$session_id DEBUG: $mod: $module_key", 14);
 
                # check if module can open msg envelope with module key
                ($msg, $msg_hash) = &check_key_and_xml_validity($input, $module_key, $session_id);
@@ -764,13 +819,13 @@ sub input_from_unknown_host {
                        next;
                } else {
                        $module = $mod;
-            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 7);
+            daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 18);
                        last;
                }
        }
 
        if( (!$msg) || (!$msg_hash) || (!$module)) {
-               daemon_log("$session_id DEBUG: Incoming message is not from an unknown host", 7);
+               daemon_log("$session_id DEBUG: Incoming message is not from an unknown host", 14);
        }
 
        return ($msg, $msg_hash, $module);
@@ -896,11 +951,14 @@ sub send_msg_to_target {
         $header = "";
     }
 
-       # Patch the source ip
-       if($msg =~ /<source>0\.0\.0\.0:\d*?<\/source>/) {
-               my $remote_ip = &get_local_ip_for_remote_ip(sprintf("%s", $address =~ /^([0-9\.]*?):.*$/));
-               $msg =~ s/<source>(0\.0\.0\.0):(\d*?)<\/source>/<source>$remote_ip:$2<\/source>/s;
-       }
+       # Memorize own source address
+       my $own_source_address = &get_local_ip_for_remote_ip(sprintf("%s", $address =~ /^([0-9\.]*?):.*$/));
+       $own_source_address .= ":".$server_port;
+
+       # Patch 0.0.0.0 source to real address
+       $msg =~ s/<source>(0\.0\.0\.0):(\d*?)<\/source>/<source>$own_source_address<\/source>/s;
+       # Patch GOSA source to real address and add forward_to_gosa tag
+       $msg =~ s/<source>GOSA<\/source>/<source>$own_source_address<\/source> <forward_to_gosa>$own_source_address,$session_id<\/forward_to_gosa>/ ;
 
     # encrypt xml msg
     my $crypted_msg = &encrypt_msg($msg, $encrypt_key);
@@ -908,16 +966,15 @@ sub send_msg_to_target {
     # opensocket
     my $socket = &open_socket($address);
     if( !$socket ) {
-        daemon_log("$session_id WARNING: cannot send ".$header."msg to $address , host not reachable", 3);
+        daemon_log("$session_id ERROR: Cannot open socket to host '$address'. Message processing aborted!", 1);
         $error++;
     }
     
     if( $error == 0 ) {
         # send xml msg
-        print $socket $crypted_msg."\n";
-
+        print $socket $crypted_msg.";$own_source_address\n";
         daemon_log("$session_id INFO: send ".$header."msg to $address", 5);
-        daemon_log("$session_id DEBUG: message:\n$msg", 9);
+        daemon_log("$session_id DEBUG: message:\n$msg", 12);
         
     }
 
@@ -945,7 +1002,7 @@ sub send_msg_to_target {
             if($new_status eq "down"){
                 daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3);
             } else {
-                daemon_log("$session_id INFO: set '$address' from status '$act_status' to '$new_status'", 5);
+                daemon_log("$session_id DEBUG: set '$address' from status '$act_status' to '$new_status'", 138);
             }
         }
     }
@@ -966,7 +1023,7 @@ sub send_msg_to_target {
             if($new_status eq "down"){
                 daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3);
             } else {
-                daemon_log("$session_id INFO: set '$address' from status '$act_status' to '$new_status'", 5);
+                daemon_log("$session_id DEBUG: set '$address' from status '$act_status' to '$new_status'", 138);
             }
         }
     }
@@ -976,8 +1033,8 @@ sub send_msg_to_target {
 
 sub update_jobdb_status_for_send_msgs {
     my ($session_id, $answer, $error) = @_;
-    &daemon_log("$session_id DEBUG: try to update job status", 7); 
     if( $answer =~ /<jobdb_id>(\d+)<\/jobdb_id>/ ) {
+               &daemon_log("$session_id DEBUG: try to update job status", 138); 
         my $jobdb_id = $1;
     
         $answer =~ /<header>(.*)<\/header>/;
@@ -995,7 +1052,6 @@ sub update_jobdb_status_for_send_msgs {
                     ||($job_header eq "trigger_action_halt") 
                     ) {
                 my $sql_statement = "UPDATE $job_queue_tn SET status='done' WHERE id=$jobdb_id";
-                &daemon_log("$session_id DEBUG: $sql_statement", 7); 
                 my $res = $job_db->update_dbentry($sql_statement);
                 
             # Reactivate jobs, jobs need to deliver their message
@@ -1004,14 +1060,22 @@ sub update_jobdb_status_for_send_msgs {
                     ||($job_header eq "trigger_action_reinstall") 
                     ||($job_header eq "trigger_activate_new")
                     ) {
-                &reactivate_job_with_delay($session_id, $job_target, $job_header, 30 );
-
+                                               if ($job_target =~ /^([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})$/i) {
+                                                       &reactivate_job_with_delay($session_id, $job_target, $job_header, 30 );
+                                               } else {
+                                                       # If we don't have the mac adress at this time, we use the plainname
+                                                       my $plainname_result = $job_db->select_dbentry("SELECT plainname from jobs where id=$jobdb_id");
+                                                       my $plainname = $job_target;
+                                                       if ((keys(%$plainname_result) > 0) ) {
+                                                               $plainname = $plainname_result->{1}->{$job_target};
+                                                       }
+                                                       &reactivate_job_with_delay($session_id, $plainname, $job_header, 30 );
+                                               }
             # For all other messages
             } else {
                 my $sql_statement = "UPDATE $job_queue_tn ".
                     "SET status='error', result='can not deliver msg, please consult log file' ".
                     "WHERE id=$jobdb_id";
-                &daemon_log("$session_id DEBUG: $sql_statement", 7); 
                 my $res = $job_db->update_dbentry($sql_statement);
             }
 
@@ -1031,14 +1095,13 @@ sub update_jobdb_status_for_send_msgs {
                 my $sql_statement = "UPDATE $job_queue_tn ".
                     "SET status='done' ".
                     "WHERE id=$jobdb_id AND status='processed'";
-                &daemon_log("$session_id DEBUG: $sql_statement", 7); 
                 my $res = $job_db->update_dbentry($sql_statement);
             } else { 
-                &daemon_log("$session_id DEBUG: sending message succeed but cannot update job status.", 7); 
+                &daemon_log("$session_id DEBUG: sending message succeed but cannot update job status.", 138); 
             } 
         } 
     } else { 
-        &daemon_log("$session_id DEBUG: cannot update job status, msg has no jobdb_id-tag: $answer", 7); 
+        &daemon_log("$session_id DEBUG: cannot update job status, msg has no jobdb_id-tag.", 138); 
     }
 }
 
@@ -1049,11 +1112,10 @@ sub reactivate_job_with_delay {
     if (not defined $delay) { $delay = 30 } ;
     my $delay_timestamp = &calc_timestamp(&get_time(), "plus", $delay);
 
-    my $sql = "UPDATE $job_queue_tn Set timestamp='$delay_timestamp', status='waiting' WHERE (macaddress LIKE 'target' AND headertag='$header')"; 
+    my $sql = "UPDATE $job_queue_tn Set timestamp='$delay_timestamp', status='waiting' WHERE (macaddress LIKE '$target' OR plainname LIKE '$target') AND headertag='$header'"; 
     my $res = $job_db->update_dbentry($sql);
     daemon_log("$session_id INFO: '$header'-job will be reactivated at '$delay_timestamp' ".
             "cause client '$target' is currently not available", 5);
-    daemon_log("$session_id $sql", 7);                             
     return;
 }
 
@@ -1080,25 +1142,60 @@ sub msg_to_decrypt {
        ($msg, $msg_hash, $module) = &input_from_unknown_host($next_msg, $session_id);
 
        # msg is from a gosa-si-server
-       if(( !$msg ) || ( !$msg_hash ) || ( !$module )){
-               ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $heap->{'remote_ip'}, $session_id);
+       if(((!$msg) || (!$msg_hash) || (!$module)) && ($serverPackages_enabled eq "true")){
+               if (not defined $msg_source) 
+               {
+                       # Only needed, to be compatible with older gosa-si-server versions
+                       ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $heap->{'remote_ip'}, $session_id);
+               }
+               else
+               {
+                       ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $msg_source, $session_id);
+               }
        }
        # msg is from a gosa-si-client
        if(( !$msg ) || ( !$msg_hash ) || ( !$module )){
-               ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $heap->{'remote_ip'}, $session_id);
+               if (not defined $msg_source) 
+               {
+                       # Only needed, to be compatible with older gosa-si-server versions
+                       ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $heap->{'remote_ip'}, $session_id);
+               }
+               else
+               {
+                       ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $msg_source, $session_id);
+               }
        }
        # an error occurred
        if(( !$msg ) || ( !$msg_hash ) || ( !$module )){
-               # if an incoming msg could not be decrypted (maybe a wrong key), send client a ping. If the client
-               # could not understand a msg from its server the client cause a re-registering process
-        my $remote_ip = $heap->{'remote_ip'};
-        my $remote_port = $heap->{'remote_port'};
-        my $ping_msg = "<xml> <header>gosa_ping</header> <source>$server_address</source><target>$msg_source</target></xml>";
-        my ($test_error, $test_error_string) = &send_msg_to_target($ping_msg, "$msg_source", "dummy-key", "gosa_ping", $session_id);
-
-               daemon_log("$session_id WARNING cannot understand incoming msg, send 'ping'-msg to all host with ip '".$heap->{remote_ip}.
-                       "' to cause a re-registering of the client if necessary", 3);
-               $error++;
+               # If an incoming msg could not be decrypted (maybe a wrong key), decide if msg comes from a client 
+               # or a server.  In case of a client, send a ping. If the client could not understand a msg from its 
+               # server the client cause a re-registering process. In case of a server, decrease update_time in kown_server_db
+               # and trigger a re-registering process for servers
+               if (defined $msg_source && $msg_source =~ /:$server_port$/ && $serverPackages_enabled eq "true")
+               {
+                       daemon_log("$session_id WARNING: Cannot understand incoming msg from server '$msg_source'. Cause re-registration process for servers.", 3);
+                       my $update_statement = "UPDATE $known_server_tn SET update_time='19700101000000' WHERE hostname='$msg_source'"; 
+                       daemon_log("$session_id DEBUG: $update_statement", 7);
+                       my $upadte_res = $known_server_db->exec_statement($update_statement);
+                       $kernel->yield("register_at_foreign_servers");
+               }
+               elsif ((defined $msg_source) && (not $msg_source =~ /:$server_port$/))
+               {
+                       daemon_log("$session_id WARNING: Cannot understand incoming msg from client '$msg_source'. Send ping-msg to cause a re-registering of the client if necessary", 3);
+                       #my $remote_ip = $heap->{'remote_ip'};
+                       #my $remote_port = $heap->{'remote_port'};
+                       my $ping_msg = "<xml> <header>gosa_ping</header> <source>$server_address</source><target>$msg_source</target></xml>";
+                       my ($test_error, $test_error_string) = &send_msg_to_target($ping_msg, "$msg_source", "dummy-key", "gosa_ping", $session_id);
+                       daemon_log("$session_id WARNING: Sending msg to cause re-registering: $ping_msg", 3);
+               }
+               else
+               {
+                       my $foreign_host = defined $msg_source ? $msg_source : $heap->{'remote_ip'};
+                       daemon_log("$session_id ERROR: Incoming message from host '$foreign_host' cannot be understood. Processing aborted!", 1);
+                       daemon_log("$session_id DEBUG: Aborted message: $tmp_next_msg", 11);
+               }
+
+               $error++
        }
 
 
@@ -1141,7 +1238,7 @@ sub msg_to_decrypt {
                if (not $done) {
                        if ($target eq "GOSA" && $source eq "GOSA") {
                                $done = 1;                    
-                               &daemon_log("$session_id DEBUG: target and source is 'GOSA' -> process here", 7);
+                               &daemon_log("$session_id DEBUG: target and source is 'GOSA' -> process '$header' here", 11);
                        }
                }
 
@@ -1153,30 +1250,11 @@ sub msg_to_decrypt {
                                if ($source eq "GOSA") {
                                        $msg =~ s/<\/xml>/<forward_to_gosa>$local_address,$session_id<\/forward_to_gosa><\/xml>/;
                                }
-                               &daemon_log("$session_id DEBUG: target is own address without forward_to_gosa-tag -> process here", 7);
+                               &daemon_log("$session_id DEBUG: target is own address without forward_to_gosa-tag -> process '$header' here", 11);
                        }
                }
 
-               # target is a client address in known_clients -> process here
-               if (not $done) {
-                       $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; 
-                       $res = $known_clients_db->select_dbentry($sql);
-                       if (keys(%$res) > 0) {
-                               $done = 1; 
-                               my $hostname = $res->{1}->{'hostname'};
-                               $msg =~ s/<target>$target<\/target>/<target>$hostname<\/target>/;
-                               my $local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port";
-                               if ($source eq "GOSA") {
-                                       $msg =~ s/<\/xml>/<forward_to_gosa>$local_address,$session_id<\/forward_to_gosa><\/xml>/;
-                               }
-                               &daemon_log("$session_id DEBUG: target is a client address in known_clients -> process here", 7);
-
-                       } else {
-                               $not_found_in_known_clients_db = 1;
-                       }
-               }
-
-               # target ist own address with forward_to_gosa-tag not pointing to myself -> process here
+               # target is own address with forward_to_gosa-tag not pointing to myself -> process here
                if (not $done) {
                        my $forward_to_gosa =  @{$msg_hash->{'forward_to_gosa'}}[0];
                        my $gosa_at;
@@ -1185,15 +1263,44 @@ sub msg_to_decrypt {
                                my ($gosa_at, $gosa_session_id) = split(/,/, $forward_to_gosa);
                                if ($gosa_at ne $local_address) {
                                        $done = 1;
-                                       &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag not pointing to myself -> process here", 7); 
+                                       &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag not pointing to myself -> process '$header' here", 11); 
                                }
                        }
                }
 
+               # Target is a client address and there is a processing function within a plugin -> process loaclly
+               if (not $done)
+               {
+                       # Check if target is a client address
+                       $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; 
+                       $res = $known_clients_db->select_dbentry($sql);
+                       if ((keys(%$res) > 0) ) 
+                       {
+                               my $hostname = $res->{1}->{'hostname'};
+                               my $reduced_header = $header;
+                               $reduced_header =~ s/gosa_//;
+                               # Check if there is a processing function within a plugin
+                               if (exists $known_functions->{$reduced_header}) 
+                               {
+                                       $msg =~ s/<target>\S*<\/target>/<target>$hostname<\/target>/;
+                                       $done = 1;
+                                       &daemon_log("$session_id DEBUG: Target is client address with processing function within a plugin -> process '$header' here", 11);
+                               }
+                       }
+               }
+
+               # If header has a 'job_' prefix, do always process message locally
+               # which means put it into job queue
+               if ((not $done) && ($header =~ /job_/))
+               {
+                       $done = 1;
+                       &daemon_log("$session_id DEBUG: Header has a 'job_' prefix. Put it into job queue. -> process '$header' here", 11);
+               }
+
                # if message should be processed here -> add message to incoming_db
                if ($done) {
-                       # if a job or a gosa message comes from a foreign server, fake module to GosaPackages
-                       # so gosa-si-server knows how to process this kind of messages
+                       # if a 'job_' or a 'gosa_' message comes from a foreign server, fake module from
+                       # ServerPackages to GosaPackages so gosa-si-server knows how to process this kind of messages
                        if ($header =~ /^gosa_/ || $header =~ /^job_/) {
                                $module = "GosaPackages";
                        }
@@ -1207,7 +1314,7 @@ sub msg_to_decrypt {
                                        module=>$module,
                                        sessionid=>$session_id,
                                } );
-
+                       $kernel->yield('watch_for_next_tasks');
                }
 
                # target is own address with forward_to_gosa-tag pointing at myself -> forward to gosa
@@ -1225,15 +1332,38 @@ sub msg_to_decrypt {
                                        if(exists $heap->{'client'}) {
                                                $msg = &encrypt_msg($msg, $GosaPackages_key);
                                                $heap->{'client'}->put($msg);
-                                               &daemon_log("$session_id INFO: incoming '$header' message forwarded to GOsa", 5); 
+                                               &daemon_log("$session_id DEBUG: incoming '$header' message forwarded to GOsa", 11); 
                                        }
                                        $done = 1;
-                                       &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag pointing at myself -> forward to gosa", 7);
+                                       &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag pointing at myself -> forward '$header' to gosa", 11);
                                }
                        }
 
                }
 
+               # target is a client address in known_clients -> forward to client
+               if (not $done) {
+                       $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; 
+                       $res = $known_clients_db->select_dbentry($sql);
+                       if (keys(%$res) > 0) 
+                       {
+                               $done = 1; 
+                               &daemon_log("$session_id DEBUG: target is a client address in known_clients -> forward '$header' to client", 11);
+                               my $hostkey = $res->{1}->{'hostkey'};
+                               my $hostname = $res->{1}->{'hostname'};
+                               $msg =~ s/<target>\S*<\/target>/<target>$hostname<\/target>/;
+                               $msg =~ s/<header>gosa_/<header>/;
+                               my $error= &send_msg_to_target($msg, $hostname, $hostkey, $header, $session_id);
+                               if ($error) {
+                                       &daemon_log("$session_id ERROR: Some problems occurred while trying to send msg to client '$hostname': $msg", 1);
+                               }
+                       } 
+                       else 
+                       {
+                               $not_found_in_known_clients_db = 1;
+                       }
+               }
+
                # target is a client address in foreign_clients -> forward to registration server
                if (not $done) {
                        $sql = "SELECT * FROM $foreign_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')";
@@ -1254,11 +1384,11 @@ sub msg_to_decrypt {
                                        }
                                        my $error= &send_msg_to_target($msg, $regserver, $regserver_key, $header, $session_id);
                                        if ($error) {
-                                               &daemon_log("$session_id ERROR: some problems (error=$error) occurred while trying to send msg to registration server: $msg", 1); 
+                                               &daemon_log("$session_id ERROR: some problems occurred while trying to send msg to registration server: $msg", 1); 
                                        }
                                }
                                $done = 1;
-                               &daemon_log("$session_id DEBUG: target is a client address in foreign_clients -> forward to registration server", 7);
+                               &daemon_log("$session_id DEBUG: target is a client address in foreign_clients -> forward '$header' to registration server", 11);
                        } else {
                                $not_found_in_foreign_clients_db = 1;
                        }
@@ -1279,7 +1409,7 @@ sub msg_to_decrypt {
 
                                &send_msg_to_target($msg, $target, $hostkey, $header, $session_id);
                                $done = 1;
-                               &daemon_log("$session_id DEBUG: target is a server address -> forward to server", 7);
+                               &daemon_log("$session_id DEBUG: target is a server address -> forward '$header' to server", 11);
                        } else {
                                $not_found_in_known_server_db = 1;
                        }
@@ -1290,7 +1420,7 @@ sub msg_to_decrypt {
                if ( $not_found_in_foreign_clients_db 
                        && $not_found_in_known_server_db
                        && $not_found_in_known_clients_db) {
-                       &daemon_log("$session_id DEBUG: target is not in foreign_clients_db, known_server_db or known_clients_db, maybe it is a complete new one -> process here", 7);
+                       &daemon_log("$session_id DEBUG: target is not in foreign_clients_db, known_server_db or known_clients_db, maybe it is a complete new one -> process '$header' here", 11);
             if ($header =~ /^gosa_/ || $header =~ /^job_/) { 
                 $module = "GosaPackages"; 
             }
@@ -1304,6 +1434,7 @@ sub msg_to_decrypt {
                                        sessionid=>$session_id,
                                } );
                        $done = 1;
+                       $kernel->yield('watch_for_next_tasks');
                }
 
 
@@ -1331,16 +1462,15 @@ sub msg_to_decrypt {
 
 
 sub next_task {
-    my ($session, $heap, $task, $ldap_handle) = @_[SESSION, HEAP, ARG0, ARG1];
+    my ($session, $heap, $task) = @_[SESSION, HEAP, ARG0, ARG1];
     my $running_task = POE::Wheel::Run->new(
-            Program => sub { process_task($session, $heap, $task, $ldap_handle) },
+            Program => sub { process_task($session, $heap, $task) },
             StdioFilter => POE::Filter::Reference->new(),
             StdoutEvent  => "task_result",
             StderrEvent  => "task_debug",
             CloseEvent   => "task_done",
             );
     $heap->{task}->{ $running_task->ID } = $running_task;
-       $heap->{ldap_handle}->{$running_task->ID} = $ldap_handle;
 }
 
 sub handle_task_result {
@@ -1378,7 +1508,7 @@ sub handle_task_done {
 sub process_task {
     no strict "refs";
     #CHECK: Not @_[...]?
-    my ($session, $heap, $task, $ldap_handle) = @_;
+    my ($session, $heap, $task) = @_;
     my $error = 0;
     my $answer_l;
     my ($answer_header, @answer_target_l, $answer_source);
@@ -1408,17 +1538,18 @@ sub process_task {
     # process incoming msg
     if( $error == 0) {
         daemon_log("$session_id INFO: Incoming msg (session_id=$session_id) with header '".@{$msg_hash->{'header'}}[0]."'", 5); 
-        daemon_log("$session_id DEBUG: Processing module ".$module, 7);
-        $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id, $ldap_handle);
+        daemon_log("$session_id DEBUG: Processing module ".$module, 26);
+        $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id);
 
         if ( 0 < @{$answer_l} ) {
             my $answer_str = join("\n", @{$answer_l});
+                       my @headers; 
             while ($answer_str =~ /<header>(\w+)<\/header>/g) {
-                daemon_log("$session_id INFO: got answer message with header '$1'", 5);
+                               push(@headers, $1);
             }
-            daemon_log("$session_id DEBUG: $module: got answer from module: \n".$answer_str,9);
+                       daemon_log("$session_id DEBUG: got answer message(s) with header: '".join("', '", @headers)."'", 26);
         } else {
-            daemon_log("$session_id DEBUG: $module: got no answer from module!" ,7);
+            daemon_log("$session_id DEBUG: $module: got no answer from module!" ,26);
         }
 
     }
@@ -1430,7 +1561,7 @@ sub process_task {
 
         foreach my $answer ( @{$answer_l} ) {
             # check outgoing msg to xml validity
-            my $answer_hash = &check_outgoing_xml_validity($answer, $session_id);
+            my ($answer, $answer_hash) = &check_outgoing_xml_validity($answer, $session_id);
             if( not defined $answer_hash ) { next; }
             
             $answer_header = @{$answer_hash->{'header'}}[0];
@@ -1474,6 +1605,9 @@ sub process_task {
                     if( defined $session_id ) {
                         $add_on = ".session_id=$session_id";
                     }
+                                       my $header = ($1) if $answer =~ /<header>(\S*)<\/header>/;
+                                       daemon_log("$session_id INFO: send ".$header." message to GOsa", 5);
+                                       daemon_log("$session_id DEBUG: message:\n$answer", 12);
                     # answer is for GOSA and has to returned to connected client
                     my $gosa_answer = &encrypt_msg($answer, $GosaPackages_key);
                     $client_answer = $gosa_answer.$add_on;
@@ -1490,7 +1624,7 @@ sub process_task {
 
                 # Target of msg is a mac address
                 elsif( $answer_target =~ /^([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})$/i ) {
-                    daemon_log("$session_id INFO: target is mac address '$answer_target', looking for host in known_clients and foreign_clients", 5);
+                    daemon_log("$session_id DEBUG: target is mac address '$answer_target', looking for host in known_clients and foreign_clients", 138);
 
                     # Looking for macaddress in known_clients
                     my $sql_statement = "SELECT * FROM known_clients WHERE macaddress LIKE '$answer_target'";
@@ -1577,7 +1711,6 @@ sub session_start {
     $kernel->yield('register_at_foreign_servers');
        $kernel->yield('create_fai_server_db', $fai_server_tn );
        $kernel->yield('create_fai_release_db', $fai_release_tn );
-    $kernel->yield('watch_for_next_tasks');
        $kernel->sig(USR1 => "sig_handler");
        $kernel->sig(USR2 => "recreate_packages_db");
        $kernel->delay_set('watch_for_new_jobs', $job_queue_loop_delay);
@@ -1597,16 +1730,35 @@ sub session_start {
 
 
 sub watch_for_done_jobs {
-       #CHECK: $heap for what?
-       my ($kernel,$heap) = @_[KERNEL, HEAP];
+       my $kernel = $_[KERNEL];
 
        my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((status='done') AND (modified='0'))";
        my $res = $job_db->select_dbentry( $sql_statement );
 
-       while( my ($id, $hit) = each %{$res} ) {
-               my $jobdb_id = $hit->{id};
-               my $sql_statement = "DELETE FROM $job_queue_tn WHERE id=$jobdb_id"; 
-               my $res = $job_db->del_dbentry($sql_statement); 
+       while( my ($number, $hit) = each %{$res} ) 
+       {
+               # Non periodical jobs can be deleted.
+               if ($hit->{periodic} eq "none")
+               {
+                       my $jobdb_id = $hit->{id};
+                       my $sql_statement = "DELETE FROM $job_queue_tn WHERE id=$jobdb_id"; 
+                       my $res = $job_db->del_dbentry($sql_statement); 
+               }
+
+               # Periodical jobs should not be deleted but reactivated with new timestamp instead.
+               else
+               {
+                       my ($p_time, $periodic) = split("_", $hit->{periodic});
+                       my $reactivated_ts = $hit->{timestamp};
+                       my $act_ts = int(&get_time());
+                       while ($act_ts > int($reactivated_ts))   # Redo calculation to avoid multiple jobs in the past
+                       {
+                               $reactivated_ts = &calc_timestamp($reactivated_ts, "plus", $p_time, $periodic);
+                       }
+                       my $sql = "UPDATE $job_queue_tn SET status='waiting', timestamp='$reactivated_ts' WHERE id='".$hit->{id}."'"; 
+                       my $res = $job_db->exec_statement($sql);
+                       &daemon_log("J INFO: Update periodical job '".$hit->{headertag}."' for client '".$hit->{targettag}."'. New execution time '$reactivated_ts'.", 5);
+               }
        }
 
        $kernel->delay_set('watch_for_done_jobs',$job_queue_loop_delay);
@@ -1615,7 +1767,6 @@ sub watch_for_done_jobs {
 
 sub watch_for_opsi_jobs {
     my ($kernel) = $_[KERNEL];
-
     # This is not very nice to look for opsi install jobs, but headertag has to be trigger_action_reinstall. The only way to identify a 
     # opsi install job is to parse the xml message. There is still the correct header.
     my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((xmlmessage LIKE '%opsi_install_client</header>%') AND (status='processing') AND (siserver='localhost'))";
@@ -1639,10 +1790,14 @@ sub watch_for_opsi_jobs {
         };
         
         my $hres = $opsi_client->call($opsi_url, $callobj);
-        #my ($hres_err, $hres_err_string) = &check_opsi_res($hres);
+               # TODO : move all opsi relevant statments to opsi plugin
+               # The following 3 lines must be tested befor they can replace the rubbish above and below !!!
+               #my ($res, $err) = &opsi_com::_getProductStates_hash(hostId=>$hostId)
+               #if (not $err) {
+               #       my $htmp = $res->{$hostId};
+               # 
         if (not &check_opsi_res($hres)) {
             my $htmp= $hres->result->{$hostId};
-        
             # Check state != not_installed or action == setup -> load and add
             my $products= 0;
             my $installed= 0;
@@ -1804,8 +1959,7 @@ sub watch_for_new_jobs {
                                        my $res_2 = $job_db->exec_statement( $sql_statement_2 );
                                        if(defined($res_2) and defined @{$res_2}[0]) {
                                                # Set status from goto-activation to 'waiting' and update timestamp
-                                               $job_db->exec_statement("UPDATE $job_queue_tn SET status='waiting' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
-                                               $job_db->exec_statement("UPDATE $job_queue_tn SET timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
+                                               $job_db->exec_statement("UPDATE $job_queue_tn SET status='waiting', timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
                                        }
                                }
                                next;
@@ -1834,7 +1988,7 @@ sub watch_for_new_jobs {
                                        my $func_error = &send_msg_to_target($job_msg, $server_address, $GosaPackages_key, $header, "J");                    
 
                                        # update status in job queue to ...
-                    # ... 'processing', for jobs: 'reinstall', 'update'
+                    # ... 'processing', for jobs: 'reinstall', 'update', activate_new
                     if (($header =~ /gosa_trigger_action_reinstall/) 
                             || ($header =~ /gosa_trigger_activate_new/)
                             || ($header =~ /gosa_trigger_action_update/)) {
@@ -1845,7 +1999,7 @@ sub watch_for_new_jobs {
                     # ... 'done', for all other jobs, they are no longer needed in the jobqueue
                     else {
                         my $sql_statement = "UPDATE $job_queue_tn SET status='done' WHERE id=$jobdb_id";
-                        my $dbres = $job_db->update_dbentry($sql_statement);
+                        my $dbres = $job_db->exec_statement($sql_statement);
                     }
                 
 
@@ -1890,7 +2044,6 @@ sub watch_for_new_messages {
                                                                                attrs => ['memberUid'],
                                                                                filter => "cn=$group_name",
                                                                                );
-                                               &release_ldap_handle($ldap_handle);
                                                if ($mesg->count) {
                                                                my @entries = $mesg->entries;
                                                                foreach my $entry (@entries) {
@@ -1904,6 +2057,7 @@ sub watch_for_new_messages {
                                                if ($mesg->code) {
                                                                daemon_log("M ERROR: unable to translate group '$group_name' to user list for message delivery: $mesg->error", 1);
                                                }
+                                               &release_ldap_handle($ldap_handle);
                                # ldap handle error ?           
                                } else {
                                        daemon_log("M ERROR: unable to translate group '$group_name' to user list for message delivery: no ldap handle available", 1);
@@ -1954,7 +2108,6 @@ sub watch_for_delivery_messages {
 
     # select outgoing messages
     my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( flag='p' AND direction='out' )";
-    #&daemon_log("0 DEBUG: $sql", 7);
     my $res = $messaging_db->exec_statement( $sql_statement );
     
     # build out msg for each    usr
@@ -1966,7 +2119,6 @@ sub watch_for_delivery_messages {
 
         # resolve usr -> host where usr is logged in
         my $sql = "SELECT * FROM $login_users_tn WHERE (user='$receiver')"; 
-        #&daemon_log("0 DEBUG: $sql", 7);
         my $res = $login_users_db->exec_statement($sql);
 
         # receiver is logged in nowhere
@@ -2056,21 +2208,18 @@ sub watch_for_done_messages {
     my ($kernel,$heap) = @_[KERNEL, HEAP];
 
     my $sql = "SELECT * FROM $messaging_tn WHERE (flag='p' AND direction='in')"; 
-    #&daemon_log("0 DEBUG: $sql", 7);
     my $res = $messaging_db->exec_statement($sql); 
 
     foreach my $hit (@{$res}) {
         my $msg_id = @{$hit}[0];
 
         my $sql = "SELECT * FROM $messaging_tn WHERE (id='$msg_id' AND direction='out' AND (NOT flag='s'))"; 
-        #&daemon_log("0 DEBUG: $sql", 7); 
         my $res = $messaging_db->exec_statement($sql);
 
         # not all usr msgs have been seen till now
         if ( ref(@$res[0]) eq "ARRAY") { next; }
         
         $sql = "DELETE FROM $messaging_tn WHERE (id='$msg_id')"; 
-        #&daemon_log("0 DEBUG: $sql", 7);
         $res = $messaging_db->exec_statement($sql);
     
     }
@@ -2129,17 +2278,13 @@ sub watch_for_next_tasks {
         }
         my $message_id = $hit->{'id'};
         my $session_id = $hit->{'sessionid'};
-        &daemon_log("$session_id DEBUG: start processing for message with incoming id: '$message_id'", 7);
+        &daemon_log("$session_id DEBUG: start processing for message with incoming id: '$message_id'", 11);
 
-               my $ldap_handle = &get_ldap_handle();
-               if (not defined $ldap_handle) { next; }
-        $kernel->yield('next_task', $hit, $ldap_handle);
+        $kernel->yield('next_task', $hit);
 
         my $sql = "DELETE FROM $incoming_tn WHERE id=$message_id";
         my $res = $incoming_db->exec_statement($sql);
     }
-
-    $kernel->delay_set('watch_for_next_tasks', 1); 
 }
 
 
@@ -2150,115 +2295,120 @@ sub get_ldap_handle {
        if (not defined $session_id ) { $session_id = 0 };
        if ($session_id =~ /[^0-9]*/) { $session_id = 0 };
 
-       (my $package, my $file, my $row, my $subroutine, my $hasArgs, my $wantArray, my $evalText, my $isRequire) = caller(1);
-       my $caller_text = "subroutin $subroutine";
+       my ($package, $file, $row, $subroutine, $hasArgs, $wantArray, $evalText, $isRequire) = caller(1);
+       my $caller_text = "subroutine $subroutine";
        if ($subroutine eq "(eval)") {
                $caller_text = "eval block within file '$file' for '$evalText'"; 
        }
-       daemon_log("$session_id INFO: new ldap handle for $caller_text required", 9);
-
-       my $ldap_handle = $ldap_pool->get();
-       
-       if (not defined $ldap_handle) {
-               daemon_log("$session_id ERROR: ldap handle for $caller_text not available", 1);
+       daemon_log("$session_id DEBUG: new ldap handle for '$caller_text' required!", 42);
+
+get_handle:
+       my $ldap_handle = Net::LDAP->new( $ldap_uri );
+       if (not ref $ldap_handle) {
+               daemon_log("$session_id ERROR: Connection to LDAP URI '$ldap_uri' failed! Retrying in $ldap_retry_sec seconds.", 1); 
+               sleep($ldap_retry_sec);
+               goto get_handle;
+       } else {
+               daemon_log("$session_id DEBUG: Connection to LDAP URI '$ldap_uri' established.", 42);
        }
+
+       $ldap_handle->bind($ldap_admin_dn, password => $ldap_admin_password) or &daemon_log("$session_id ERROR: Could not bind as '$ldap_admin_dn' to LDAP URI '$ldap_uri'!", 1);
        return $ldap_handle;
 }
 
+
 sub release_ldap_handle {
-       my ($ldap_handle) = @_ ;
-       $ldap_pool->free($ldap_handle);
+       my ($ldap_handle, $session_id) = @_ ;
+       if (not defined $session_id ) { $session_id = 0 };
+
+       if(ref $ldap_handle) {
+         $ldap_handle->disconnect();
+  }
+       &main::daemon_log("$session_id DEBUG: Released a ldap handle!", 42);
        return;
 }
 
 
 sub change_fai_state {
-    my ($st, $targets, $session_id) = @_;
-    $session_id = 0 if not defined $session_id;
-    # Set FAI state to localboot
-    my %mapActions= (
-        reboot    => '',
-        update    => 'softupdate',
-        localboot => 'localboot',
-        reinstall => 'install',
-        rescan    => '',
-        wake      => '',
-        memcheck  => 'memcheck',
-        sysinfo   => 'sysinfo',
-        install   => 'install',
-    );
-
-    # Return if this is unknown
-    if (!exists $mapActions{ $st }){
-        daemon_log("$session_id ERROR: unknown action '$st', can not translate ot FAIstate", 1); 
-      return;
-    }
+       my ($st, $targets, $session_id) = @_;
+       $session_id = 0 if not defined $session_id;
+       # Set FAI state to localboot
+       my %mapActions= (
+               reboot    => '',
+               update    => 'softupdate',
+               localboot => 'localboot',
+               reinstall => 'install',
+               rescan    => '',
+               wake      => '',
+               memcheck  => 'memcheck',
+               sysinfo   => 'sysinfo',
+               install   => 'install',
+       );
 
-    my $state= $mapActions{ $st };
+       # Return if this is unknown
+       if (!exists $mapActions{ $st }){
+               daemon_log("$session_id ERROR: unknown action '$st', can not translate ot FAIstate", 1); 
+               return;
+       }
 
-    #if( defined($ldap_handle) ) {
+       my $state= $mapActions{ $st };
 
-      # Build search filter for hosts
-        my $search= "(&(objectClass=GOhard)";
-        foreach (@{$targets}){
-            $search.= "(macAddress=$_)";
-        }
-        $search.= ")";
+       # Build search filter for hosts
+       my $search= "(&(objectClass=GOhard)";
+       foreach (@{$targets}){
+               $search.= "(macAddress=$_)";
+       }
+       $search.= ")";
 
-      # If there's any host inside of the search string, procress them
-        if (!($search =~ /macAddress/)){
-            daemon_log("$session_id ERROR: no macAddress found in filter statement for LDAP search: '$search'", 1);    
-            return;
-        }
+       # If there's any host inside of the search string, procress them
+       if (!($search =~ /macAddress/)){
+               daemon_log("$session_id ERROR: no macAddress found in filter statement for LDAP search: '$search'", 1);    
+               return;
+       }
 
        my $ldap_handle = &get_ldap_handle($session_id);
-      # Perform search for Unit Tag
-      my $mesg = $ldap_handle->search(
-          base   => $ldap_base,
-          scope  => 'sub',
-          attrs  => ['dn', 'FAIstate', 'objectClass'],
-          filter => "$search"
-          );
+       # Perform search for Unit Tag
+       my $mesg = $ldap_handle->search(
+               base   => $ldap_base,
+               scope  => 'sub',
+               attrs  => ['dn', 'FAIstate', 'objectClass'],
+               filter => "$search"
+       );
 
-         if ($mesg->count) {
-                 my @entries = $mesg->entries;
-                 if (0 == @entries) {
-                                 daemon_log("$session_id ERROR: ldap search failed: ldap_base=$ldap_base, filter=$search", 1); 
-                 }
-
-                 foreach my $entry (@entries) {
-                         # Only modify entry if it is not set to '$state'
-                         if ($entry->get_value("FAIstate") ne "$state"){
-                                 daemon_log("$session_id INFO: Setting FAIstate to '$state' for ".$entry->dn, 5);
-                                 my $result;
-                                 my %tmp = map { $_ => 1 } $entry->get_value("objectClass");
-                                 if (exists $tmp{'FAIobject'}){
-                                         if ($state eq ''){
-                                                 $result= $ldap_handle->modify($entry->dn, changes => [ delete => [ FAIstate => [] ] ]);
-                                         } else {
-                                                 $result= $ldap_handle->modify($entry->dn, changes => [ replace => [ FAIstate => $state ] ]);
-                                         }
-                                 } elsif ($state ne ''){
-                                         $result= $ldap_handle->modify($entry->dn, changes => [ add => [ objectClass => 'FAIobject' ], add => [ FAIstate => $state ] ]);
-                                 }
-
-                                 # Errors?
-                                 if ($result->code){
-                                         daemon_log("$session_id Error: Setting FAIstate to '$state' for ".$entry->dn. "failed: ".$result->error, 1);
-                                 }
-                         } else {
-                                 daemon_log("$session_id DEBUG FAIstate at host '".$entry->dn."' already at state '$st'", 7); 
-                         }  
-                 }
-         } else {
-               daemon_log("$session_id ERROR: LDAP search failed: ldap_base=$ldap_base, filter=$search", 1);
-         }
-         &release_ldap_handle($ldap_handle);             
+       if ($mesg->count) {
+               my @entries = $mesg->entries;
+               if (0 == @entries) {
+                       daemon_log("$session_id ERROR: ldap search failed: ldap_base=$ldap_base, filter=$search", 1); 
+               }
 
-    # if no ldap handle defined
-    #} else {
-    #    daemon_log("$session_id ERROR: no LDAP handle defined for update FAIstate", 1); 
-    #}
+               foreach my $entry (@entries) {
+                       # Only modify entry if it is not set to '$state'
+                       if ($entry->get_value("FAIstate") ne "$state"){
+                               daemon_log("$session_id INFO: Setting FAIstate to '$state' for ".$entry->dn, 5);
+                               my $result;
+                               my %tmp = map { $_ => 1 } $entry->get_value("objectClass");
+                               if (exists $tmp{'FAIobject'}){
+                                       if ($state eq ''){
+                                               $result= $ldap_handle->modify($entry->dn, changes => [ delete => [ FAIstate => [] ] ]);
+                                       } else {
+                                               $result= $ldap_handle->modify($entry->dn, changes => [ replace => [ FAIstate => $state ] ]);
+                                       }
+                               } elsif ($state ne ''){
+                                       $result= $ldap_handle->modify($entry->dn, changes => [ add => [ objectClass => 'FAIobject' ], add => [ FAIstate => $state ] ]);
+                               }
+
+                               # Errors?
+                               if ($result->code){
+                                       daemon_log("$session_id Error: Setting FAIstate to '$state' for ".$entry->dn. "failed: ".$result->error, 1);
+                               }
+                       } else {
+                               daemon_log("$session_id DEBUG FAIstate at host '".$entry->dn."' already at state '$st'", 42); 
+                       }  
+               }
+       } else {
+               daemon_log("$session_id ERROR: LDAP search failed: ldap_base=$ldap_base, filter=$search", 1);
+       }
+       &release_ldap_handle($ldap_handle, $session_id);                  
 
        return;
 }
@@ -2283,6 +2433,7 @@ sub change_goto_state {
 
       # If there's any host inside of the search string, procress them
       if (!($search =~ /macAddress/)){
+             &release_ldap_handle($ldap_handle);
         return;
       }
 
@@ -2317,7 +2468,7 @@ sub change_goto_state {
          }
 
     }
-       &release_ldap_handle($ldap_handle);
+       &release_ldap_handle($ldap_handle, $session_id);
        return;
 }
 
@@ -2335,29 +2486,24 @@ sub run_recreate_packages_db {
 sub run_create_fai_server_db {
     my ($kernel, $session, $heap, $table_name) = @_[KERNEL, SESSION, HEAP, ARG0];
     my $session_id = $session->ID;
-       my $ldap_handle = &get_ldap_handle();
-       if (not defined $ldap_handle) {
-               $kernel->delay_set('create_fai_server_db', 1, $table_name);
-               return;
-       }
     my $task = POE::Wheel::Run->new(
-            Program => sub { &create_fai_server_db($table_name,$kernel, undef, $session_id, $ldap_handle) },
+            Program => sub { &create_fai_server_db($table_name,$kernel, undef, $session_id) },
             StdoutEvent  => "session_run_result",
             StderrEvent  => "session_run_debug",
             CloseEvent   => "session_run_done",
             );
 
     $heap->{task}->{ $task->ID } = $task;
-       $heap->{ldap_handle}->{$task->ID} = $ldap_handle;
     return;
 }
 
 
 sub create_fai_server_db {
-       my ($table_name, $kernel, $dont_create_packages_list, $session_id, $ldap_handle) = @_;
+       my ($table_name, $kernel, $dont_create_packages_list, $session_id) = @_;
        my $result;
 
        if (not defined $session_id) { $session_id = 0; }
+       my $ldap_handle = &get_ldap_handle($session_id);
        if(defined($ldap_handle)) {
                daemon_log("$session_id INFO: create_fai_server_db: start", 5);
                my $mesg= $ldap_handle->search(
@@ -2387,6 +2533,7 @@ sub create_fai_server_db {
                        }
                }
                daemon_log("$session_id INFO: create_fai_server_db: finished", 5);
+               &release_ldap_handle($ldap_handle);
 
                # TODO: Find a way to post the 'create_packages_list_db' event
                if(not defined($dont_create_packages_list)) {
@@ -2401,32 +2548,26 @@ sub create_fai_server_db {
 sub run_create_fai_release_db {
        my ($kernel, $session, $heap, $table_name) = @_[KERNEL, SESSION, HEAP, ARG0];
        my $session_id = $session->ID;
-       my $ldap_handle = &get_ldap_handle();
-       if (not defined $ldap_handle) {
-               $kernel->delay_set('create_fai_release_db', 1, $table_name);
-               return;
-       }
        my $task = POE::Wheel::Run->new(
-               Program => sub { &create_fai_release_db($table_name, $session_id, $ldap_handle) },
+               Program => sub { &create_fai_release_db($table_name, $session_id) },
                StdoutEvent  => "session_run_result",
                StderrEvent  => "session_run_debug",
                CloseEvent   => "session_run_done",
        );
 
        $heap->{task}->{ $task->ID } = $task;
-       $heap->{ldap_handle}->{$task->ID} = $ldap_handle;
        return;
 }
 
 
 sub create_fai_release_db {
-       my ($table_name, $session_id, $ldap_handle) = @_;
+       my ($table_name, $session_id) = @_;
        my $result;
 
        # used for logging
        if (not defined $session_id) { $session_id = 0; }
 
-       #my $ldap_handle = &get_ldap_handle();
+       my $ldap_handle = &get_ldap_handle($session_id);
        if(defined($ldap_handle)) {
                daemon_log("$session_id INFO: create_fai_release_db: start",5);
                my $mesg= $ldap_handle->search(
@@ -2437,7 +2578,7 @@ sub create_fai_release_db {
                );
                if(($mesg->code == 0) && ($mesg->count != 0))
                {
-                       daemon_log("$session_id DEBUG: create_fai_release_db: count " . $mesg->count,8);
+                       daemon_log("$session_id DEBUG: create_fai_release_db: count " . $mesg->count,138);
 
                        # Walk through all possible FAI container ou's
                        my @sql_list;
@@ -2464,19 +2605,19 @@ sub create_fai_release_db {
                                }
                        }
 
-                       daemon_log("$session_id DEBUG: create_fai_release_db: Inserting ".scalar @sql_list." entries to DB",8);
+                       daemon_log("$session_id DEBUG: create_fai_release_db: Inserting ".scalar @sql_list." entries to DB",138);
+           &release_ldap_handle($ldap_handle);
                        if(@sql_list) {
                                unshift @sql_list, "VACUUM";
                                unshift @sql_list, "DELETE FROM $table_name";
                                $fai_release_db->exec_statementlist(\@sql_list);
                        }
-                       daemon_log("$session_id DEBUG: create_fai_release_db: Done with inserting",7);
+                       daemon_log("$session_id DEBUG: create_fai_release_db: Done with inserting",138);
                } else {
                        daemon_log("$session_id INFO: create_fai_release_db: error: " . $mesg->code, 5);
                }
                daemon_log("$session_id INFO: create_fai_release_db: finished",5);
        }
-       #&release_ldap_handle($ldap_handle);
        return $result;
 }
 
@@ -2521,14 +2662,14 @@ sub resolve_fai_classes {
        my $fai_filter= "(|(&(objectClass=FAIclass)(|(objectClass=".join(")(objectClass=", @possible_fai_classes).")))(objectClass=FAIbranch))";
        my $fai_classes;
 
-       daemon_log("$session_id DEBUG: Searching for FAI entries in base $fai_base",7);
+       daemon_log("$session_id DEBUG: Searching for FAI entries in base $fai_base", 138);
        my $mesg= $ldap_handle->search(
                base   => $fai_base,
                scope  => 'sub',
                attrs  => ['cn','objectClass','FAIstate'],
                filter => $fai_filter,
        );
-       daemon_log("$session_id DEBUG: Found ".$mesg->count()." FAI entries",7);
+       daemon_log("$session_id DEBUG: Found ".$mesg->count()." FAI entries", 138);
 
        if($mesg->{'resultCode'} == 0 &&
                $mesg->count != 0) {
@@ -2729,7 +2870,7 @@ sub session_run_done {
 
 
 sub create_sources_list {
-       my $session_id = shift;
+       my $session_id = shift || 0;
        my $result="/tmp/gosa_si_tmp_sources_list";
 
        # Remove old file
@@ -2738,21 +2879,19 @@ sub create_sources_list {
                &main::daemon_log("$session_id DEBUG: remove an old version of '$result'", 7); 
        }
 
-       my $fh;
-       open($fh, ">$result");
+       open(my $fh, ">", "$result");
        if (not defined $fh) {
                &main::daemon_log("$session_id DEBUG: cannot open '$result' for writing", 7); 
                return undef;
        }
        if(defined($main::ldap_server_dn) and length($main::ldap_server_dn) > 0) {
-               my $ldap_handle = &get_ldap_handle();
+               my $ldap_handle = &get_ldap_handle($session_id);
                my $mesg=$ldap_handle->search(
                        base    => $main::ldap_server_dn,
                        scope   => 'base',
                        attrs   => 'FAIrepository',
                        filter  => 'objectClass=FAIrepositoryServer'
                );
-               &release_ldap_handle($ldap_handle);
                if($mesg->count) {
                        foreach my $entry(@{$mesg->{'entries'}}) {
                                foreach my $value(@{$entry->get_value('FAIrepository', asref => 1)}) {
@@ -2764,6 +2903,7 @@ sub create_sources_list {
                                }
                        }
                }
+               &release_ldap_handle($ldap_handle);
        } else {
                if (defined $main::ldap_server_dn){
                        &main::daemon_log("$session_id ERROR: something wrong with ldap_server_dn '$main::ldap_server_dn', abort create_sources_list", 1); 
@@ -2822,14 +2962,14 @@ sub create_packages_list_db {
 
        my $line;
 
-       open(CONFIG, "<$sources_file") or do {
+       open(my $CONFIG, "<", "$sources_file") or do {
                daemon_log( "$session_id ERROR: create_packages_list_db: Failed to open '$sources_file'", 1);
                unlink($packages_list_under_construction);
                return;
        };
 
        # Read lines
-       while ($line = <CONFIG>){
+       while ($line = <$CONFIG>){
                # Unify
                chop($line);
                $line =~ s/^\s+//;
@@ -2851,9 +2991,12 @@ sub create_packages_list_db {
                                &parse_package_info( $baseurl, $dist, $section, $session_id );
                        }
                }
+    else {
+        daemon_log("$session_id ERROR: cannot parse line '$line'", 1);
+    }
        }
 
-       close (CONFIG);
+       close ($CONFIG);
 
        if(keys(%repo_dirs)) {
                find(\&cleanup_and_extract, keys( %repo_dirs ));
@@ -3009,7 +3152,7 @@ sub parse_package_info {
     $repo_dirs{ "${repo_path}/pool" } = 1;
 
     foreach $package ("Packages.gz"){
-        daemon_log("$session_id DEBUG: create_packages_list: fetch $baseurl, $dist, $section", 7);
+        daemon_log("$session_id DEBUG: create_packages_list: fetch $baseurl, $dist, $section", 266);
         get_package( "$baseurl/dists/$dist/$section/binary-$arch/$package", "$outdir/$dist/$section", $session_id );
         parse_package( "$outdir/$dist/$section", $dist, $path, $session_id );
     }
@@ -3027,9 +3170,9 @@ sub get_package {
     # This is ugly, but I've no time to take a look at "how it works in perl"
     if(0 == system("wget '$url' -O '$dest' 2>/dev/null") ) {
         system("gunzip -cd '$dest' > '$dest.in'");
-        daemon_log("$session_id DEBUG: run command: gunzip -cd '$dest' > '$dest.in'", 5);
+        daemon_log("$session_id DEBUG: run command: gunzip -cd '$dest' > '$dest.in'", 266);
         unlink($dest);
-        daemon_log("$session_id DEBUG: delete file '$dest'", 5); 
+        daemon_log("$session_id DEBUG: delete file '$dest'", 266); 
     } else {
         daemon_log("$session_id ERROR: create_packages_list_db: get_packages: fetching '$url' into '$dest' failed!", 1);
     }
@@ -3041,7 +3184,6 @@ sub parse_package {
     my ($path, $dist, $srv_path, $session_id)= @_;
     if (not defined $session_id) { $session_id = 0;}
     my ($package, $version, $section, $description);
-    my $PACKAGES;
     my $timestamp = &get_time();
 
     if(not stat("$path.in")) {
@@ -3049,7 +3191,7 @@ sub parse_package {
         return;
     }
 
-    open($PACKAGES, "<$path.in");
+    open(my $PACKAGES, "<", "$path.in");
     if(not defined($PACKAGES)) {
         daemon_log("$session_id ERROR: create_packages_list_db: parse_package: cannot open '$path.in'",1); 
         return;
@@ -3136,13 +3278,13 @@ sub cleanup_and_extract {
 
                if( -f "$dir/DEBIAN/templates" ) {
 
-                       daemon_log("0 DEBUG: Found debconf templates in '$package' - $newver", 7);
+                       daemon_log("0 DEBUG: Found debconf templates in '$package' - $newver", 266);
 
                        my $tmpl= ""; {
                                local $/=undef;
-                               open FILE, "$dir/DEBIAN/templates";
-                               $tmpl = &encode_base64(<FILE>);
-                               close FILE;
+                               open(my $FILE, "$dir/DEBIAN/templates");
+                               $tmpl = &encode_base64(<$FILE>);
+                               close($FILE);
                        }
                        rmtree("$dir/DEBIAN/templates");
 
@@ -3155,57 +3297,163 @@ sub cleanup_and_extract {
 }
 
 
+sub prepare_server_registration 
+{
+       # Add foreign server from cfg file
+       my @foreign_server_list;
+       if ($foreign_server_string ne "") {
+           my @cfg_foreign_server_list = split(",", $foreign_server_string);
+           foreach my $foreign_server (@cfg_foreign_server_list) {
+               push(@foreign_server_list, $foreign_server);
+           }
+       
+           daemon_log("0 INFO: found foreign server in config file: ".join(", ", @foreign_server_list), 5);
+       }
+       
+       # Perform a DNS lookup for server registration if flag is true
+       if ($dns_lookup eq "true") {
+           # Add foreign server from dns
+           my @tmp_servers;
+           if (not $server_domain) {
+               # Try our DNS Searchlist
+               for my $domain(get_dns_domains()) {
+                   chomp($domain);
+                   my ($tmp_domains, $error_string) = &get_server_addresses($domain);
+                   if(@$tmp_domains) {
+                       for my $tmp_server(@$tmp_domains) {
+                           push @tmp_servers, $tmp_server;
+                       }
+                   }
+               }
+               if(@tmp_servers && length(@tmp_servers)==0) {
+                   daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3);
+               }
+           } else {
+               @tmp_servers = &get_server_addresses($server_domain);
+               if( 0 == @tmp_servers ) {
+                   daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3);
+               }
+           }
+       
+           daemon_log("0 INFO: found foreign server via DNS ".join(", ", @tmp_servers), 5);    
+       
+           foreach my $server (@tmp_servers) { 
+               unshift(@foreign_server_list, $server); 
+           }
+       } else {
+           daemon_log("0 INFO: DNS lookup for server registration is disabled", 5);
+       }
+       
+       # eliminate duplicate entries
+       @foreign_server_list = &del_doubles(@foreign_server_list);
+       my $all_foreign_server = join(", ", @foreign_server_list);
+       daemon_log("0 INFO: found foreign server in config file and DNS: '$all_foreign_server'", 5);
+       
+       # add all found foreign servers to known_server
+       my $cur_timestamp = &get_time();
+       foreach my $foreign_server (@foreign_server_list) {
+       
+               # do not add myself to known_server_db
+               if (&is_local($foreign_server)) { next; }
+               ######################################
+       
+           my $res = $known_server_db->add_dbentry( {table=>$known_server_tn, 
+                   primkey=>['hostname'],
+                   hostname=>$foreign_server,
+                   macaddress=>"",
+                   status=>'not_yet_registered',
+                   hostkey=>"none",
+                   loaded_modules => "none", 
+                   timestamp=>$cur_timestamp,
+                               update_time=>'19700101000000',
+                   } );
+       }
+}
+
 sub register_at_foreign_servers {   
     my ($kernel) = $_[KERNEL];
 
-    # hole alle bekannten server aus known_server_db
-    my $server_sql = "SELECT * FROM $known_server_tn";
-    my $server_res = $known_server_db->exec_statement($server_sql);
+       # Update status and update-time of all si-server with expired update_time and 
+       # block them for race conditional registration processes of other si-servers.
+       my $act_time = &get_time();
+       my $block_statement = "UPDATE $known_server_tn SET status='new_server',update_time='19700101000000' WHERE (CAST(update_time AS UNSIGNED))<$act_time ";
+       my $block_res = $known_server_db->exec_statement($block_statement);
 
-    # no entries in known_server_db
-    if (not ref(@$server_res[0]) eq "ARRAY") { 
-        # TODO
-    }
+       # Fetch all si-server from db where update_time is younger than act_time
+       my $fetch_statement = "SELECT * FROM $known_server_tn WHERE update_time='19700101000000'"; 
+       my $fetch_res = $known_server_db->exec_statement($fetch_statement);
 
-    # detect already connected clients
+    # Detect already connected clients. Will be added to registration msg later. 
     my $client_sql = "SELECT * FROM $known_clients_tn"; 
     my $client_res = $known_clients_db->exec_statement($client_sql);
 
-    # send my server details to all other gosa-si-server within the network
-    foreach my $hit (@$server_res) {
+       # Send registration messag to all fetched si-server
+    foreach my $hit (@$fetch_res) {
         my $hostname = @$hit[0];
         my $hostkey = &create_passwd;
 
-        # add already connected clients to registration message 
+        # Add already connected clients to registration message 
         my $myhash = &create_xml_hash('new_server', $server_address, $hostname);
         &add_content2xml_hash($myhash, 'key', $hostkey);
         map(&add_content2xml_hash($myhash, 'client', @{$_}[0].",".@{$_}[4]), @$client_res);
 
-        # add locally loaded gosa-si modules to registration message
+        # Add locally loaded gosa-si modules to registration message
         my $loaded_modules = {};
         while (my ($package, $pck_info) = each %$known_modules) {
-                                               next if ((!defined(@$pck_info[2])) || (!(ref (@$pck_info[2]) eq 'HASH')));
-                                               foreach my $act_module (keys(%{@$pck_info[2]})) {
-                                                       $loaded_modules->{$act_module} = ""; 
-                                               }
-        }
-
+                       next if ((!defined(@$pck_info[2])) || (!(ref (@$pck_info[2]) eq 'HASH')));
+                       foreach my $act_module (keys(%{@$pck_info[2]})) {
+                               $loaded_modules->{$act_module} = ""; 
+                       }
+               }
         map(&add_content2xml_hash($myhash, "loaded_modules", $_), keys(%$loaded_modules));
 
-        # add macaddress to registration message
+        # Add macaddress to registration message
         my ($host_ip, $host_port) = split(/:/, $hostname);
         my $local_ip = &get_local_ip_for_remote_ip($host_ip);
         my $network_interface= &get_interface_for_ip($local_ip);
         my $host_mac = &get_mac_for_interface($network_interface);
         &add_content2xml_hash($myhash, 'macaddress', $host_mac);
         
-        # build registration message and send it
+        # Build registration message and send it
         my $foreign_server_msg = &create_xml_string($myhash);
         my $error = &send_msg_to_target($foreign_server_msg, $hostname, $ServerPackages_key, "new_server", 0); 
     }
-    
-    $kernel->delay_set("register_at_foreign_servers", $foreign_servers_register_delay); 
-    return;
+
+
+       # After n sec perform a check of all server registration processes
+    $kernel->delay_set("control_server_registration", 2); 
+
+       return;
+}
+
+
+sub control_server_registration {
+       my ($kernel) = $_[KERNEL];
+       
+       # Check if all registration processes succeed or not
+       my $select_statement = "SELECT * FROM $known_server_tn WHERE status='new_server'"; 
+       my $select_res = $known_server_db->exec_statement($select_statement);
+
+       # If at least one registration process failed, maybe in case of a race condition
+       # with a foreign registration process
+       if (@$select_res > 0) 
+       {
+               # Release block statement 'new_server' to make the server accessible
+               # for foreign registration processes
+               my $update_statement = "UPDATE $known_server_tn SET status='waiting' WHERE status='new_server'";        
+               my $update_res = $known_server_db->exec_statement($update_statement);
+
+               # Set a random delay to avoid the registration race condition
+               my $new_foreign_servers_register_delay = int(rand(4))+1;
+               $kernel->delay_set("register_at_foreign_servers", $new_foreign_servers_register_delay);
+       }
+       # If all registration processes succeed
+       else
+       {
+               $kernel->delay_set("register_at_foreign_servers", $foreign_servers_register_delay);
+       }
+
+       return;
 }
 
 
@@ -3217,7 +3465,8 @@ GetOptions("h|help" => \&usage,
         "f|foreground" => \$foreground,
         "v|verbose+" => \$verbose,
         "no-arp+" => \$no_arp,
-           );
+               "d=s" => \$debug_parts,
+           ) or &usage("", 1); 
 
 #  read and set config parameters
 &check_cmdline_param ;
@@ -3245,9 +3494,9 @@ if( ! $foreground ) {
 
 # 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 );
+    open( my $LOCK_FILE, ">", "$pid_file" );
+    print $LOCK_FILE "$pid\n";
+    close( $LOCK_FILE );
     if( !$foreground ) { 
         exit( 0 ) 
     };
@@ -3267,8 +3516,8 @@ if ($server_headURL =~ /\/tag\// ||
 # Prepare log file and set permissions
 $root_uid = getpwnam('root');
 $adm_gid = getgrnam('adm');
-open(FH, ">>$log_file");
-close FH;
+open(my $FH, ">>", "$log_file");
+close($FH);
 chmod(0440, $log_file);
 chown($root_uid, $adm_gid, $log_file);
 chown($root_uid, $adm_gid, "/var/lib/gosa-si");
@@ -3278,22 +3527,14 @@ daemon_log("$0 started!", 1);
 daemon_log("status: $server_status", 1);
 daemon_log($server_status_hash->{$server_status}.": $server_revision", 1); 
 
-# Create a pool of LDAP handles
-$ldap_factory =  ResourcePool::Factory::Net::LDAP->new($ldap_uri, version => $ldap_version);
-$ldap_factory->bind($ldap_admin_dn, password=>$ldap_admin_password);
-$ldap_pool = ResourcePool->new($ldap_factory,
-               Max         => $max_ldap_handle,
-               #MaxTry      => 1,
-               #SleepOnFail    => [0, 0, 1, 1],
-               PreCreate       => $precreate_ldap_handle,
-);
-
-
 # Buildup data bases
 {
     no strict "refs";
 
     if ($db_module eq "DBmysql") {
+
+        daemon_log("0 INFO: importing database module '$db_module'", 1);
+
         # connect to incoming_db
         $incoming_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password);
 
@@ -3325,9 +3566,14 @@ $ldap_pool = ResourcePool->new($ldap_factory,
         $messaging_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password);
 
     } elsif ($db_module eq "DBsqlite") {
+
+        daemon_log("0 INFO: importing database module '$db_module'", 1);
+
         # connect to incoming_db
         unlink($incoming_file_name);
         $incoming_db = GOSA::DBsqlite->new($incoming_file_name);
+        chmod(0640, $incoming_file_name);
+        chown($root_uid, $adm_gid, $incoming_file_name);
         
         # connect to gosa-si job queue
         $job_db = GOSA::DBsqlite->new($job_queue_file_name);
@@ -3335,24 +3581,25 @@ $ldap_pool = ResourcePool->new($ldap_factory,
         chown($root_uid, $adm_gid, $job_queue_file_name);
         
         # connect to known_clients_db
+        #unlink($known_clients_file_name);
         $known_clients_db = GOSA::DBsqlite->new($known_clients_file_name);
         chmod(0640, $known_clients_file_name);
         chown($root_uid, $adm_gid, $known_clients_file_name);
         
         # connect to foreign_clients_db
-        unlink($foreign_clients_file_name);
+        #unlink($foreign_clients_file_name);
         $foreign_clients_db = GOSA::DBsqlite->new($foreign_clients_file_name);
         chmod(0640, $foreign_clients_file_name);
         chown($root_uid, $adm_gid, $foreign_clients_file_name);
         
         # connect to known_server_db
-        unlink($known_server_file_name);
+        unlink($known_server_file_name);   # do not delete, gosa-si-server should be forced to check config file and dns at each start
         $known_server_db = GOSA::DBsqlite->new($known_server_file_name);
         chmod(0640, $known_server_file_name);
         chown($root_uid, $adm_gid, $known_server_file_name);
         
         # connect to login_usr_db
-        unlink($login_users_file_name);
+        #unlink($login_users_file_name);
         $login_users_db = GOSA::DBsqlite->new($login_users_file_name);
         chmod(0640, $login_users_file_name);
         chown($root_uid, $adm_gid, $login_users_file_name);
@@ -3370,22 +3617,23 @@ $ldap_pool = ResourcePool->new($ldap_factory,
         chown($root_uid, $adm_gid, $fai_release_file_name);
         
         # connect to packages_list_db
-        #unlink($packages_list_file_name);
         unlink($packages_list_under_construction);
         $packages_list_db = GOSA::DBsqlite->new($packages_list_file_name);
         chmod(0640, $packages_list_file_name);
         chown($root_uid, $adm_gid, $packages_list_file_name);
         
         # connect to messaging_db
-        unlink($messaging_file_name);
+        #unlink($messaging_file_name);
         $messaging_db = GOSA::DBsqlite->new($messaging_file_name);
         chmod(0640, $messaging_file_name);
         chown($root_uid, $adm_gid, $messaging_file_name);
     }
 }
 
-
 # Creating tables
+
+daemon_log("0 INFO: creating tables in database with '$db_module'", 1);
+
 $messaging_db->create_table($messaging_tn, \@messaging_col_names);
 $packages_list_db->create_table($packages_list_tn, \@packages_list_col_names);
 $fai_release_db->create_table($fai_release_tn, \@fai_release_col_names);
@@ -3400,86 +3648,27 @@ $job_db->create_table($job_queue_tn, \@job_queue_col_names);
 # create xml object used for en/decrypting
 $xml = new XML::Simple();
 
-
-# foreign servers 
-my @foreign_server_list;
-
-# add foreign server from cfg file
-if ($foreign_server_string ne "") {
-    my @cfg_foreign_server_list = split(",", $foreign_server_string);
-    foreach my $foreign_server (@cfg_foreign_server_list) {
-        push(@foreign_server_list, $foreign_server);
-    }
-
-    daemon_log("0 INFO: found foreign server in config file: ".join(", ", @foreign_server_list), 5);
-}
-
-# Perform a DNS lookup for server registration if flag is true
-if ($dns_lookup eq "true") {
-    # Add foreign server from dns
-    my @tmp_servers;
-    if (not $server_domain) {
-        # Try our DNS Searchlist
-        for my $domain(get_dns_domains()) {
-            chomp($domain);
-            my ($tmp_domains, $error_string) = &get_server_addresses($domain);
-            if(@$tmp_domains) {
-                for my $tmp_server(@$tmp_domains) {
-                    push @tmp_servers, $tmp_server;
-                }
-            }
-        }
-        if(@tmp_servers && length(@tmp_servers)==0) {
-            daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3);
-        }
-    } else {
-        @tmp_servers = &get_server_addresses($server_domain);
-        if( 0 == @tmp_servers ) {
-            daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3);
-        }
-    }
-
-    daemon_log("0 INFO: found foreign server via DNS ".join(", ", @tmp_servers), 5);    
-
-    foreach my $server (@tmp_servers) { 
-        unshift(@foreign_server_list, $server); 
-    }
-} else {
-    daemon_log("0 INFO: DNS lookup for server registration is disabled", 5);
-}
-
-
-# eliminate duplicate entries
-@foreign_server_list = &del_doubles(@foreign_server_list);
-my $all_foreign_server = join(", ", @foreign_server_list);
-daemon_log("0 INFO: found foreign server in config file and DNS: '$all_foreign_server'", 5);
-
-# add all found foreign servers to known_server
-my $cur_timestamp = &get_time();
-foreach my $foreign_server (@foreign_server_list) {
-
-       # do not add myself to known_server_db
-       if (&is_local($foreign_server)) { next; }
-       ######################################
-
-    my $res = $known_server_db->add_dbentry( {table=>$known_server_tn, 
-            primkey=>['hostname'],
-            hostname=>$foreign_server,
-            macaddress=>"",
-            status=>'not_yet_registered',
-            hostkey=>"none",
-            loaded_modules => "none", 
-            timestamp=>$cur_timestamp,
-            } );
-}
-
-
 # Import all modules
 &import_modules;
 
 # Check wether all modules are gosa-si valid passwd check
 &password_check;
 
+# Check DNS and config file for server registration
+if ($serverPackages_enabled eq "true") { &prepare_server_registration; }
+
+# Create functions hash
+while (my ($module, @mod_info) = each %$known_modules) 
+{
+       while (my ($plugin, $functions) = each %{$mod_info[0][2]})
+       {
+               while (my ($function, $nothing) = each %$functions )
+               {
+                       $known_functions->{$function} = $nothing;
+               }
+       }
+}
+
 # Prepare for using Opsi 
 if ($opsi_enabled eq "true") {
     use JSON::RPC::Client;
@@ -3495,13 +3684,26 @@ POE::Component::Server::TCP->new(
        ClientInput => sub {
                my ($kernel, $input, $heap, $session) = @_[KERNEL, ARG0, HEAP, SESSION];
         my $session_id = $session->ID;
-        my $remote_ip = $heap->{'remote_ip'};
+               if ($input =~ /;([\d\.]+):([\d]+)$/) 
+               {
+                       # Messages from other servers should be blocked if config option is set
+                       if (($2 eq $server_port) && ($serverPackages_enabled eq "false"))
+                       {
+                               return;
+                       }
+                       &daemon_log("$session_id DEBUG: incoming message from '$1:$2'", 11);
+               }
+               else
+               {
+                       my $remote_ip = $heap->{'remote_ip'};
+                       &daemon_log("$session_id DEBUG: incoming message from '$remote_ip'", 11);
+               }
                push(@msgs_to_decrypt, $input);
-        &daemon_log("$session_id DEBUG: incoming message from '$remote_ip'", 7);
                $kernel->yield("msg_to_decrypt");
        },
        InlineStates => {
                msg_to_decrypt => \&msg_to_decrypt,
+               watch_for_next_tasks => \&watch_for_next_tasks,
                next_task => \&next_task,
                task_result => \&handle_task_result,
                task_done   => \&handle_task_done,
@@ -3517,12 +3719,12 @@ POE::Session->create(
        inline_states => {
                _start => \&session_start,
         register_at_foreign_servers => \&register_at_foreign_servers,
+               control_server_registration => \&control_server_registration,
         sig_handler => \&sig_handler,
         next_task => \&next_task,
         task_result => \&handle_task_result,
         task_done   => \&handle_task_done,
         task_debug  => \&handle_task_debug,
-        watch_for_next_tasks => \&watch_for_next_tasks,
         watch_for_new_messages => \&watch_for_new_messages,
         watch_for_delivery_messages => \&watch_for_delivery_messages,
         watch_for_done_messages => \&watch_for_done_messages,