index c273341cffe41d23de65814f51ad22c8c971ebf5..00def48475f2a6e23380df446f3d58e25854fcef 100644 (file)
use XML::Simple;
use Data::Dumper;
use Net::LDAP;
-use Socket qw/PF_INET SOCK_DGRAM inet_ntoa sockaddr_in/;
+use Socket;
+use Net::hostent;
BEGIN{}
END {}
my ($known_clients_file_name);
-my ($server_activ, $server_ip, $server_mac_address, $server_port, $server_passwd, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password);
+my ($server_activ, $server_ip, $server_mac_address, $server_port, $SIPackages_key, $max_clients, $ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password);
my ($bus_activ, $bus_passwd, $bus_ip, $bus_port);
my $server;
my $network_interface;
"server_ip" => [\$server_ip, "0.0.0.0"],
"server_mac_address" => [\$server_mac_address, ""],
"server_port" => [\$server_port, "20081"],
- "server_passwd" => [\$server_passwd, ""],
+ "SIPackages_key" => [\$SIPackages_key, ""],
"max_clients" => [\$max_clients, 100],
"ldap_uri" => [\$ldap_uri, ""],
"ldap_base" => [\$ldap_base, ""],
®ister_at_bus();
}
+# add myself to known_server_db
+my $res = $main::known_server_db->add_dbentry( {table=>'known_server',
+ primkey=>'hostname',
+ hostname=>$server_address,
+ status=>'myself',
+ hostkey=>$SIPackages_key,
+ timestamp=>&get_time,
+ } );
+
+
+
### functions #################################################################
sub get_module_info {
my @info = ($server_address,
- $server_passwd,
+ $SIPackages_key,
$server,
$server_activ,
"socket",
}
+
+sub do_wake {
+ my $host = shift;
+ my $ipaddr = shift || '255.255.255.255';
+ my $port = getservbyname('discard', 'udp');
+
+ my ($raddr, $them, $proto);
+ my ($hwaddr, $hwaddr_re, $pkt);
+
+ # get the hardware address (ethernet address)
+
+ $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
+ if ($host =~ m/^$hwaddr_re$/) {
+ $hwaddr = $host;
+ } else {
+ # $host is not a hardware address, try to resolve it
+ my $ip_re = join('\.', ('([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))') x 4);
+ my $ip_addr;
+ if ($host =~ m/^$ip_re$/) {
+ $ip_addr = $host;
+ } else {
+ my $h;
+ unless ($h = gethost($host)) {
+ return undef;
+ }
+ $ip_addr = inet_ntoa($h->addr);
+ }
+ }
+
+ # Generate magic sequence
+ foreach (split /:/, $hwaddr) {
+ $pkt .= chr(hex($_));
+ }
+ $pkt = chr(0xFF) x 6 . $pkt x 16;
+
+ # Allocate socket and send packet
+
+ $raddr = gethostbyname($ipaddr)->addr;
+ $them = pack_sockaddr_in($port, $raddr);
+ $proto = getprotobyname('udp');
+
+ socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
+ setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
+
+ send(S, $pkt, 0, $them) or die "send : $!";
+ close S;
+}
+
+
#=== FUNCTION ================================================================
# NAME: read_configfile
# PARAMETERS: cfg_file - string -
timestamp=>&get_time,
} );
my $msg_hash = &create_xml_hash("here_i_am", $server_address, $bus_address);
- my $answer = "";
- $answer = &send_msg_hash2address($msg_hash, $bus_address, $bus_passwd);
- if ($answer == 0) {
- &main::daemon_log("register at bus: $bus_address", 1);
- } else {
- &main::daemon_log("unable to send 'register'-msg to bus '$bus_address': $answer", 1);
- }
- return;
+ my $msg = &create_xml_string($msg_hash);
+ return $msg;
+# my $answer = "";
+# $answer = &send_msg_hash2address($msg_hash, $bus_address, $bus_passwd);
+# if ($answer == 0) {
+# &main::daemon_log("register at bus: $bus_address", 1);
+# } else {
+# &main::daemon_log("unable to send 'register'-msg to bus '$bus_address': $answer", 1);
+# }
+# return;
}
# DESCRIPTION: handels the proceeded distribution to the appropriated functions
#===============================================================================
sub process_incoming_msg {
- my ($msg, $msg_hash) = @_ ;
+ my ($msg, $msg_hash, $remote_ip) = @_ ;
my $error = 0;
my $host_name;
my $host_key;
# process incoming msg
my $header = @{$msg_hash->{header}}[0];
- my $source = @{$msg_hash->{source}}[0];
my @target_l = @{$msg_hash->{target}};
&main::daemon_log("SIPackages: msg to process: $header", 3);
if( 1 == length @target_l) {
my $target = $target_l[0];
if( $target eq $server_address ) {
- if ($header eq 'new_passwd') { @out_msg_l = &new_passwd($msg_hash) }
- elsif ($header eq 'here_i_am') { @out_msg_l = &here_i_am($msg_hash) }
- elsif ($header eq 'who_has') { @out_msg_l = &who_has($msg_hash) }
- elsif ($header eq 'who_has_i_do') { @out_msg_l = &who_has_i_do($msg_hash) }
- elsif ($header eq 'got_ping') { @out_msg_l = &got_ping($msg_hash)}
- elsif ($header eq 'get_load') { @out_msg_l = &execute_actions($msg_hash)}
- else {
- &main::daemon_log("ERROR: $header is an unknown core funktion", 1);
+ if ($header eq 'new_key') {
+ @out_msg_l = &new_key($msg_hash)
+ } elsif ($header eq 'here_i_am') {
+ @out_msg_l = &here_i_am($msg_hash)
+ } elsif ($header eq 'who_has') {
+ @out_msg_l = &who_has($msg_hash)
+ } elsif ($header eq 'who_has_i_do') {
+ @out_msg_l = &who_has_i_do($msg_hash)
+ } elsif ($header eq 'got_ping') {
+ @out_msg_l = &got_ping($msg_hash)
+ } elsif ($header eq 'get_load') {
+ @out_msg_l = &execute_actions($msg_hash)
+ } elsif ($header eq 'detected_hardware') {
+ @out_msg_l = &process_detected_hardware($msg_hash)
+ } elsif ($header eq 'trigger_wake') {
+ foreach (@{$msg_hash->{macAddress}}){
+ &main::daemon_log("SIPackages: trigger wake for $_", 1);
+ do_wake($_);
+ }
+
+ } else {
+ &main::daemon_log("ERROR: $header is an unknown core function", 1);
$error++;
}
}
# RETURNS: nothing
# DESCRIPTION: process this incoming message
#===============================================================================
-sub new_passwd {
+sub new_key {
my ($msg_hash) = @_;
my @out_msg_l;
my $header = @{$msg_hash->{header}}[0];
my $source_name = @{$msg_hash->{source}}[0];
- my $source_key = @{$msg_hash->{new_passwd}}[0];
+ my $source_key = @{$msg_hash->{new_key}}[0];
my $query_res;
# check known_clients_db
"SET hostkey='$source_key', timestamp='$act_time' ".
"WHERE hostname='$source_name'";
my $res = $main::known_clients_db->update_dbentry( $sql_statement );
-
my $hash = &create_xml_hash("confirm_new_passwd", $server_address, $source_name);
my $out_msg = &create_xml_string($hash);
push(@out_msg_l, $out_msg);
my $source = @{$msg_hash->{source}}[0];
my $mac_address = @{$msg_hash->{mac_address}}[0];
+ my $gotoHardwareChecksum = @{$msg_hash->{gotoHardwareChecksum}}[0];
# number of known clients
my $nu_clients= $main::known_clients_db->count_dbentries('known_clients');
push(@out_msg_l, $new_ldap_config_out);
}
+ my $hardware_config_out = &hardware_config($source, $gotoHardwareChecksum);
+ if( $hardware_config_out ) {
+ push(@out_msg_l, $hardware_config_out);
+ }
return @out_msg_l;
}
#===============================================================================
sub who_has {
my ($msg_hash) = @_ ;
+ my @out_msg_l;
# what is your search pattern
my $search_pattern = @{$msg_hash->{who_has}}[0];
# search was successful
if (defined $host_address) {
my $source = @{$msg_hash->{source}}[0];
- my $out_msg = &create_xml_hash("who_has_i_do", $server_address, $source, "mac_address");
- &add_content2xml_hash($out_msg, "mac_address", $search_element);
- &send_msg_hash2address($out_msg, $bus_address);
+ my $out_hash = &create_xml_hash("who_has_i_do", $server_address, $source, "mac_address");
+ &add_content2xml_hash($out_hash, "mac_address", $search_element);
+ my $out_msg = &create_xml_string($out_hash);
+ push(@out_msg_l, $out_msg);
}
- return;
+ return @out_msg_l;
}
print "\ngot msg $header:\nserver $source has client with $search_param $search_value\n";
}
-
#=== FUNCTION ================================================================
# NAME: new_ldap_config
# PARAMETERS: address - string - ip address and port of a host
# DESCRIPTION: send to address the ldap configuration found for dn gotoLdapServer
#===============================================================================
sub new_ldap_config {
- my ($address) = @_ ;
-
+ my ($address) = @_ ;
+
+ my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
+ my $res = $main::known_clients_db->select_dbentry( $sql_statement );
+
+ # check hit
+ my $hit_counter = keys %{$res};
+ if( not $hit_counter == 1 ) {
+ &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
+ }
+
+ my $macaddress = $res->{1}->{macaddress};
+ my $hostkey = $res->{1}->{hostkey};
+
+ if (not defined $macaddress) {
+ &main::daemon_log("ERROR: no mac address found for client $address", 1);
+ return;
+ }
+
+ # Build LDAP connection
+ my $ldap = Net::LDAP->new($ldap_uri);
+ if( not defined $ldap ) {
+ &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1);
+ return;
+ }
+
+
+ # Bind to a directory with dn and password
+ my $mesg= $ldap->bind($ldap_admin_dn, password => $ldap_admin_password);
+
+ # Perform search
+ $mesg = $ldap->search( base => $ldap_base,
+ scope => 'sub',
+ attrs => ['dn', 'gotoLdapServer', 'gosaUnitTag'],
+ filter => "(&(objectClass=GOhard)(macaddress=$macaddress))");
+ #$mesg->code && die $mesg->error;
+ if($mesg->code) {
+ &main::daemon_log($mesg->error, 1);
+ return;
+ }
+
+ # Sanity check
+ if ($mesg->count != 1) {
+ &main::daemon_log("WARNING: client mac address $macaddress not found/not unique in ldap search", 1);
+ &main::daemon_log("\tbase: $ldap_base", 1);
+ &main::daemon_log("\tscope: sub", 1);
+ &main::daemon_log("\tattrs: dn, gotoLdapServer", 1);
+ &main::daemon_log("\tfilter: (&(objectClass=GOhard)(macaddress=$macaddress))", 1);
+ return;
+ }
+
+ my $entry= $mesg->entry(0);
+ my $dn= $entry->dn;
+ my @servers= $entry->get_value("gotoLdapServer");
+ my $unit_tag= $entry->get_value("gosaUnitTag");
+ my @ldap_uris;
+ my $server;
+ my $base;
+
+ # Do we need to look at an object class?
+ if (length(@servers) < 1){
+ $mesg = $ldap->search( base => $ldap_base,
+ scope => 'sub',
+ attrs => ['dn', 'gotoLdapServer'],
+ filter => "(&(objectClass=gosaGroupOfNames)(member=$dn))");
+ #$mesg->code && die $mesg->error;
+ if($mesg->code) {
+ &main::daemon_log($mesg->error, 1);
+ return;
+ }
+
+ # Sanity check
+ if ($mesg->count != 1) {
+ &main::daemon_log("WARNING: no LDAP information found for client mac $macaddress", 1);
+ return;
+ }
+
+ $entry= $mesg->entry(0);
+ $dn= $entry->dn;
+ @servers= $entry->get_value("gotoLdapServer");
+ }
+
+ @servers= sort (@servers);
+
+ foreach $server (@servers){
+ $base= $server;
+ $server =~ s%^[^:]+:[^:]+:(ldap.*://[^/]+)/.*$%$1%;
+ $base =~ s%^[^:]+:[^:]+:ldap.*://[^/]+/(.*)$%$1%;
+ push (@ldap_uris, $server);
+ }
+
+ # Assemble data package
+ my %data = ( 'ldap_uri' => \@ldap_uris, 'ldap_base' => $base,
+ 'ldap_cfg' => \@ldap_cfg, 'pam_cfg' => \@pam_cfg,'nss_cfg' => \@nss_cfg );
+
+ # Need to append GOto settings?
+ if (defined $goto_admin and defined $goto_secret){
+ $data{'goto_admin'}= $goto_admin;
+ $data{'goto_secret'}= $goto_secret;
+ }
+
+ # Append unit tag if needed
+ if (defined $unit_tag){
+
+ # Find admin base and department name
+ $mesg = $ldap->search( base => $ldap_base,
+ scope => 'sub',
+ attrs => ['dn', 'ou'],
+ filter => "(&(objectClass=gosaAdministrativeUnit)(gosaUnitTag=$unit_tag))");
+ #$mesg->code && die $mesg->error;
+ if($mesg->code) {
+ &main::daemon_log($mesg->error, 1);
+ return;
+ }
+
+ # Sanity check
+ if ($mesg->count != 1) {
+ &main::daemon_log("WARNING: cannot find administrative unit for client with tag $unit_tag", 1);
+ return;
+ }
+
+ $entry= $mesg->entry(0);
+ $data{'admin_base'}= $entry->dn;
+ $data{'department'}= $entry->get_value("ou");
+
+ # Append unit Tag
+ $data{'unit_tag'}= $unit_tag;
+ }
+
+ # Unbind
+ $mesg = $ldap->unbind;
+
+ # Send information
+ return send_msg("new_ldap_config", $server_address, $address, \%data);
+}
+
+sub process_detected_hardware {
+ my $msg_hash = shift;
+ my $address = $msg_hash->{source}[0];
+
my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
my $res = $main::known_clients_db->select_dbentry( $sql_statement );
&main::daemon_log("ERROR: no mac address found for client $address", 1);
return;
}
-
# Build LDAP connection
my $ldap = Net::LDAP->new($ldap_uri);
if( not defined $ldap ) {
return;
}
-
# Bind to a directory with dn and password
- my $mesg= $ldap->bind($ldap_admin_dn, $ldap_admin_password);
+ my $mesg= $ldap->bind($ldap_admin_dn, password => $ldap_admin_password);
# Perform search
- $mesg = $ldap->search( base => $ldap_base,
- scope => 'sub',
- attrs => ['dn', 'gotoLdapServer'],
- filter => "(&(objectClass=GOhard)(macaddress=$macaddress))");
- $mesg->code && die $mesg->error;
-
- # Sanity check
- if ($mesg->count != 1) {
- &main::daemon_log("WARNING: client mac address $macaddress not found/not unique in ldap search", 1);
- &main::daemon_log("\tbase: $ldap_base", 1);
- &main::daemon_log("\tscope: sub", 1);
- &main::daemon_log("\tattrs: dn, gotoLdapServer", 1);
- &main::daemon_log("\tfilter: (&(objectClass=GOhard)(macaddress=$macaddress))", 1);
- return;
- }
+ $mesg = $ldap->search(
+ base => $ldap_base,
+ scope => 'sub',
+ filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
+ );
+
+ if($mesg->count == 1) {
+ my $entry= $mesg->entry(0);
+ $entry->changetype("modify");
+ foreach my $attribute (
+ "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel",
+ "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync",
+ "gotoXDriver", "gotoXVsync", "gotoXMonitor") {
+ if(defined($msg_hash->{detected_hardware}[0]->{$attribute})) {
+ if(defined($entry->get_value($attribute))) {
+ $entry->delete($attribute);
+ }
+ &main::daemon_log("Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},1);
+ $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});
+ }
+ }
+ foreach my $attribute (
+ "gotoModules", "ghScsiDev", "ghIdeDev") {
+ if(defined($msg_hash->{detected_hardware}[0]->{$attribute})) {
+ if(defined($entry->get_value($attribute))) {
+ $entry->delete($attribute);
+ }
+ foreach my $array_entry (@{$msg_hash->{detected_hardware}[0]->{$attribute}}) {
+ $entry->add($attribute => $array_entry);
+ }
+ }
- my $entry= $mesg->entry(0);
- my $dn= $entry->dn;
- my @servers= $entry->get_value("gotoLdapServer");
- my @ldap_uris;
- my $server;
- my $base;
-
- # Do we need to look at an object class?
- if (length(@servers) < 1){
- $mesg = $ldap->search( base => $ldap_base,
- scope => 'sub',
- attrs => ['dn', 'gotoLdapServer'],
- filter => "(&(objectClass=gosaGroupOfNames)(member=$dn))");
- $mesg->code && die $mesg->error;
-
- # Sanity check
- if ($mesg->count != 1) {
- &main::daemon_log("WARNING: no LDAP information found for client mac $macaddress", 1);
- return;
- }
-
- $entry= $mesg->entry(0);
- $dn= $entry->dn;
- @servers= $entry->get_value("gotoLdapServer");
- }
+ }
+ if($entry->update($ldap)) {
+ &main::daemon_log("Added Hardware configuration to LDAP", 4);
+ }
+
+ }
+ return;
+}
+#=== FUNCTION ================================================================
+# NAME: hardware_config
+# PARAMETERS: address - string - ip address and port of a host
+# RETURNS:
+# DESCRIPTION:
+#===============================================================================
+sub hardware_config {
+ my ($address, $gotoHardwareChecksum) = @_ ;
- @servers= sort (@servers);
+ my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
+ my $res = $main::known_clients_db->select_dbentry( $sql_statement );
- foreach $server (@servers){
- $base= $server;
- $server =~ s%^[^:]+:[^:]+:(ldap.*://[^/]+)/.*$%$1%;
- $base =~ s%^[^:]+:[^:]+:ldap.*://[^/]+/(.*)$%$1%;
- push (@ldap_uris, $server);
- }
+ # check hit
+ my $hit_counter = keys %{$res};
+ if( not $hit_counter == 1 ) {
+ &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
+ }
- # Unbind
- $mesg = $ldap->unbind;
+ my $macaddress = $res->{1}->{macaddress};
+ my $hostkey = $res->{1}->{hostkey};
- # Assemble data package
- my %data = ( 'ldap_uri' => \@ldap_uris, 'ldap_base' => $base,
- 'ldap_cfg' => \@ldap_cfg, 'pam_cfg' => \@pam_cfg,'nss_cfg' => \@nss_cfg );
+ if (not defined $macaddress) {
+ &main::daemon_log("ERROR: no mac address found for client $address", 1);
+ return;
+ }
- # Need to append GOto settings?
- if (defined $goto_admin and defined $goto_secret){
- $data{'goto_admin'}= $goto_admin;
- $data{'goto_secret'}= $goto_secret;
- }
+ # Build LDAP connection
+ my $ldap = Net::LDAP->new($ldap_uri);
+ if( not defined $ldap ) {
+ &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1);
+ return;
+ }
+
+ # Bind to a directory with dn and password
+ my $mesg= $ldap->bind($ldap_admin_dn, password => $ldap_admin_password);
+
+ # Perform search
+ $mesg = $ldap->search(
+ base => $ldap_base,
+ scope => 'sub',
+ filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
+ );
+
+ if($mesg->count() == 0) {
+ &main::daemon_log("Host was not found in LDAP!", 1);
+ return;
+ }
+
+ my $entry= $mesg->entry(0);
+ my $dn= $entry->dn;
+ if(defined($entry->get_value("gotoHardwareChecksum"))) {
+ if(! $entry->get_value("gotoHardwareChecksum") eq $gotoHardwareChecksum) {
+ $entry->replace(gotoHardwareChecksum => $gotoHardwareChecksum);
+ if($entry->update($ldap)) {
+ &main::daemon_log("Hardware changed! Detection triggered.", 4);
+ }
+ } else {
+ # Nothing to do
+ return;
+ }
+ } else {
+ # need to fill it to LDAP
+ $entry->add(gotoHardwareChecksum => $gotoHardwareChecksum);
+ if($entry->update($ldap)) {
+ &main::daemon_log("gotoHardwareChecksum $gotoHardwareChecksum was added to LDAP", 4);
+ }
+
+ ## Look if there another host with this checksum to use the hardware config
+ #$mesg = $ldap->search(
+ # base => $ldap_base,
+ # scope => 'sub',
+ # filter => "(&(objectClass=GOhard)(gotoHardwareChecksum=$gotoHardwareChecksum))"
+ #);
+
+ #if($mesg->count>1) {
+ # my $clone_entry= $mesg->entry(0);
+ # $entry->changetype("modify");
+ # foreach my $attribute (
+ # "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel",
+ # "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync",
+ # "gotoXDriver", "gotoXVsync", "gotoXMonitor") {
+ # my $value= $clone_entry->get_value($attribute);
+ # if(defined($value)) {
+ # if(defined($entry->get_value($attribute))) {
+ # $entry->delete($attribute);
+ # }
+ # &main::daemon_log("Adding attribute $attribute with value $value",1);
+ # $entry->add($attribute => $value);
+ # }
+ # }
+ # foreach my $attribute (
+ # "gotoModules", "ghScsiDev", "ghIdeDev") {
+ # my $array= $clone_entry->get_value($attribute, 'as_ref' => 1);
+ # if(defined($array)) {
+ # if(defined($entry->get_value($attribute))) {
+ # $entry->delete($attribute);
+ # }
+ # foreach my $array_entry (@{$array}) {
+ # $entry->add($attribute => $array_entry);
+ # }
+ # }
+
+ # }
+ # if($entry->update($ldap)) {
+ # &main::daemon_log("Added Hardware configuration to LDAP", 4);
+ # }
+
+ #}
+
+ }
+
+ # Assemble data package
+ my %data = ();
+
+ # Need to append GOto settings?
+ if (defined $goto_admin and defined $goto_secret){
+ $data{'goto_admin'}= $goto_admin;
+ $data{'goto_secret'}= $goto_secret;
+ }
+
+ # Unbind
+ $mesg = $ldap->unbind;
- # Send information
- return send_msg("new_ldap_config", $server_address, $address, \%data, $hostkey);
+ &main::daemon_log("Send detect_hardware message to $address", 4);
+
+ # Send information
+ return send_msg("detect_hardware", $server_address, $address, \%data);
}