X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fmodules%2FSIPackages.pm;h=f346ae26d566b13b025f7dcb572d6c2d7cb9e0ad;hb=db15b7b88560f1ee2f3f3178883511739f1b21fd;hp=4e2e0279b231aae4eb0ef3b3482e2c794ab3d920;hpb=4e4d7a89391a2aa4a38d7c383d4b8477440a1938;p=gosa.git diff --git a/gosa-si/modules/SIPackages.pm b/gosa-si/modules/SIPackages.pm index 4e2e0279b..f346ae26d 100644 --- a/gosa-si/modules/SIPackages.pm +++ b/gosa-si/modules/SIPackages.pm @@ -13,13 +13,14 @@ use IO::Socket::INET; 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; @@ -34,7 +35,7 @@ my %cfg_defaults = "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, ""], @@ -76,12 +77,23 @@ if($bus_activ eq "on") { ®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", @@ -90,6 +102,55 @@ sub get_module_info { } + +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 - @@ -280,14 +341,16 @@ sub register_at_bus { 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; } @@ -320,14 +383,29 @@ sub process_incoming_msg { 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_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) + } elsif ($header eq 'detected_hardware') { + @out_msg_l = &process_detected_hardware($msg_hash) + } elsif ($header eq 'trigger_wake') { + my $in_hash= &transform_msg2hash($msg); + foreach (@{$in_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++; } } @@ -435,6 +513,7 @@ sub here_i_am { 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'); @@ -511,6 +590,10 @@ sub here_i_am { 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; } @@ -524,6 +607,7 @@ sub here_i_am { #=============================================================================== sub who_has { my ($msg_hash) = @_ ; + my @out_msg_l; # what is your search pattern my $search_pattern = @{$msg_hash->{who_has}}[0]; @@ -545,11 +629,12 @@ sub who_has { # 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; } @@ -562,7 +647,6 @@ sub who_has_i_do { 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 @@ -570,7 +654,156 @@ sub who_has_i_do { # 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; + + + return; +} +#=== FUNCTION ================================================================ +# NAME: hardware_config +# PARAMETERS: address - string - ip address and port of a host +# RETURNS: +# DESCRIPTION: +#=============================================================================== +sub hardware_config { + my ($address, $gotoHardwareChecksum) = @_ ; my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'"; my $res = $main::known_clients_db->select_dbentry( $sql_statement ); @@ -596,66 +829,40 @@ sub new_ldap_config { 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', 'gosaUnitTag'], - 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; - } - - 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; - - # 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); + $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; + } - foreach $server (@servers){ - $base= $server; - $server =~ s%^[^:]+:[^:]+:(ldap.*://[^/]+)/.*$%$1%; - $base =~ s%^[^:]+:[^:]+:ldap.*://[^/]+/(.*)$%$1%; - push (@ldap_uris, $server); - } + my $entry= $mesg->entry(0); + my $dn= $entry->dn; + if(defined($entry->get_value("gotoHardwareChecksum"))) { + return; + } else { + # need to fill it to LDAP + $entry->add(gotoHardwareChecksum => $gotoHardwareChecksum); + &main::daemon_log(Dumper($entry->update($ldap)),1); + + # 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))" + ); + } # Assemble data package - my %data = ( 'ldap_uri' => \@ldap_uris, 'ldap_base' => $base, - 'ldap_cfg' => \@ldap_cfg, 'pam_cfg' => \@pam_cfg,'nss_cfg' => \@nss_cfg ); + my %data = (); # Need to append GOto settings? if (defined $goto_admin and defined $goto_secret){ @@ -663,35 +870,12 @@ sub new_ldap_config { $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; - - # 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; + &main::daemon_log("Send detect_hardware message to $address", 4); # Send information - return send_msg("new_ldap_config", $server_address, $address, \%data, $hostkey); + return send_msg("detect_hardware", $server_address, $address, \%data); }