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