Code

Updated wake
[gosa.git] / gosa-si / server / events / siTriggered.pm
1 package siTriggered;
2 use Exporter;
3 @ISA = qw(Exporter);
4 my @events = (
5     "got_ping",
6     "detected_hardware",
7     "trigger_wake",
8     "reload_ldap_config",
9     );
10 @EXPORT = @events;
12 use strict;
13 use warnings;
14 use GOSA::GosaSupportDaemon;
15 use Socket;
16 use Net::hostent;
19 BEGIN {}
21 END {}
23 ### Start ######################################################################
25 my $ldap_uri;
26 my $ldap_base;
27 my $ldap_admin_dn;
28 my $ldap_admin_password;
29 my $mesg;
31 my %cfg_defaults = (
32 "server" => {
33     "ldap-uri" => [\$ldap_uri, ""],
34     "ldap-base" => [\$ldap_base, ""],
35     "ldap-admin-dn" => [\$ldap_admin_dn, ""],
36     "ldap-admin-password" => [\$ldap_admin_password, ""],
37     },
38 );
39 &read_configfile($main::cfg_file, %cfg_defaults);
42 sub get_events {
43     return \@events;
44 }
47 sub read_configfile {
48     my ($cfg_file, %cfg_defaults) = @_;
49     my $cfg;
51     if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
52         if( -r $cfg_file ) {
53             $cfg = Config::IniFiles->new( -file => $cfg_file );
54         } else {
55             &main::daemon_log("ERROR: siTriggered.pm couldn't read config file!", 1);
56         }
57     } else {
58         $cfg = Config::IniFiles->new() ;
59     }
60     foreach my $section (keys %cfg_defaults) {
61         foreach my $param (keys %{$cfg_defaults{ $section }}) {
62             my $pinfo = $cfg_defaults{ $section }{ $param };
63             ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
64         }
65     }
66 }
69 sub reload_ldap_config {
70     my ($msg, $msg_hash, $session_id) = @_;
71     my $header = @{$msg_hash->{header}}[0];
72     my $target = @{$msg_hash->{$header}}[0];
74     my $out_msg = &SIPackages::new_ldap_config($target);
75     my @out_msg_l = ( $out_msg );
76     return @out_msg_l;
77 }
80 sub got_ping {
81     my ($msg, $msg_hash, $session_id) = @_;
83     my $source = @{$msg_hash->{source}}[0];
84     my $target = @{$msg_hash->{target}}[0];
85     my $header = @{$msg_hash->{header}}[0];
86     my $act_time = &get_time;
87     my @out_msg_l;
88     my $out_msg;
90     $session_id = @{$msg_hash->{'session_id'}}[0];
92     # check known_clients_db
93     my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source'";
94     my $query_res = $main::known_clients_db->select_dbentry( $sql_statement );
95     if( 1 == keys %{$query_res} ) {
96          my $sql_statement= "UPDATE known_clients ".
97             "SET status='$header', timestamp='$act_time' ".
98             "WHERE hostname='$source'";
99          my $res = $main::known_clients_db->update_dbentry( $sql_statement );
100     } 
101     
102     # check known_server_db
103     $sql_statement = "SELECT * FROM known_server WHERE hostname='$source'";
104     $query_res = $main::known_server_db->select_dbentry( $sql_statement );
105     if( 1 == keys %{$query_res} ) {
106          my $sql_statement= "UPDATE known_server ".
107             "SET status='$header', timestamp='$act_time' ".
108             "WHERE hostname='$source'";
109          my $res = $main::known_server_db->update_dbentry( $sql_statement );
110     } 
112     # create out_msg
113     my $out_hash = &create_xml_hash($header, $source, "GOSA");
114     &add_content2xml_hash($out_hash, "session_id", $session_id);
115     $out_msg = &create_xml_string($out_hash);
116     push(@out_msg_l, $out_msg);
117     
118     return @out_msg_l;
122 sub detected_hardware {
123         my ($msg, $msg_hash, $session_id) = @_ ;
124         my $address = $msg_hash->{source}[0];
125         my $gotoHardwareChecksum= $msg_hash->{detected_hardware}[0]->{gotoHardwareChecksum};
127         my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
128         my $res = $main::known_clients_db->select_dbentry( $sql_statement );
130         # check hit
131         my $hit_counter = keys %{$res};
132         if( not $hit_counter == 1 ) {
133                 &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
134                 return;
135         }
137         my $macaddress = $res->{1}->{macaddress};
138         my $hostkey = $res->{1}->{hostkey};
140         if (not defined $macaddress) {
141                 &main::daemon_log("ERROR: no mac address found for client $address", 1);
142                 return;
143         }
144         # Build LDAP connection
145         &main::refresh_ldap_handle();
146         if( not defined $main::ldap_handle ) {
147                 &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1);
148                 return;
149         } 
151         # Perform search
152         $mesg = $main::ldap_handle->search(
153                 base   => $ldap_base,
154                 scope  => 'sub',
155                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
156         );
158         # We need to create a base entry first (if not done from ArpHandler)
159         if($mesg->count == 0) {
160                 &main::daemon_log("INFO: Need to create a new LDAP Entry for client $address", 4);
161                 my $ipaddress= $1 if $address =~ /^([0-9\.]*?):.*$/;
162                 my $dnsname;
163                 if (defined($msg_hash->{'force-hostname'}) && 
164                         defined($msg_hash->{'force-hostname'}[0]) &&
165                         length($msg_hash->{'force-hostname'}[0]) > 0){
166                         $dnsname= $msg_hash->{'force-hostname'}[0];
167                         &main::daemon_log("INFO: Using forced hostname $dnsname for client $address", 4);
168                 } else {
169                         $dnsname= gethostbyaddr(inet_aton($ipaddress), AF_INET) || $ipaddress;
170                 }
172                 my $cn = (($dnsname =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/) ? $dnsname : sprintf "%s", $dnsname =~ /([^\.]+)\.?/);
173                 my $dn = "cn=$cn,ou=incoming,$ldap_base";
174                 &main::daemon_log("INFO: Creating entry for $dn",5);
175                 my $entry= Net::LDAP::Entry->new( $dn );
176                 $entry->dn($dn);
177                 $entry->add("objectClass" => "goHard");
178                 $entry->add("cn" => $cn);
179                 $entry->add("macAddress" => $macaddress);
180                 $entry->add("gotomode" => "locked");
181                 $entry->add("gotoSysStatus" => "new-system");
182                 $entry->add("ipHostNumber" => $ipaddress);
183                 if(defined($main::gosa_unit_tag) && length($main::gosa_unit_tag) > 0) {
184                         $entry->add("objectClass" => "gosaAdministrativeUnitTag");
185                         $entry->add("gosaUnitTag" => $main::gosa_unit_tag);
186                 }
187                 my $res=$entry->update($main::ldap_handle);
188                 if(defined($res->{'errorMessage'}) &&
189                         length($res->{'errorMessage'}) >0) {
190                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
191                         return;
192                 } else {
193                         # Fill $mesg again
194                         $mesg = $main::ldap_handle->search(
195                                 base   => $ldap_base,
196                                 scope  => 'sub',
197                                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
198                         );
199                 }
200         }
202         if($mesg->count == 1) {
203                 my $entry= $mesg->entry(0);
204                 $entry->changetype("modify");
205                 foreach my $attribute (
206                         "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel", 
207                         "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync", 
208                         "gotoXDriver", "gotoXVsync", "gotoXMonitor", "gotoHardwareChecksum") {
209                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
210                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
211                                 if(defined($entry->get_value($attribute))) {
212                                         $entry->delete($attribute);
213                                 }
214                                 &main::daemon_log("INFO: Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},5);
215                                 $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});     
216                         }
217                 }
218                 foreach my $attribute (
219                         "gotoModules", "ghScsiDev", "ghIdeDev") {
220                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
221                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
222                                 if(defined($entry->get_value($attribute))) {
223                                         $entry->delete($attribute);
224                                 }
225                                 foreach my $array_entry (@{$msg_hash->{detected_hardware}[0]->{$attribute}}) {
226                                         $entry->add($attribute => $array_entry);
227                                 }
228                         }
229                 }
231                 my $res=$entry->update($main::ldap_handle);
232                 if(defined($res->{'errorMessage'}) &&
233                         length($res->{'errorMessage'}) >0) {
234                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
235                 } else {
236                         &main::daemon_log("INFO: Added Hardware configuration to LDAP", 5);
237                 }
239         }
240         return ;
244 sub trigger_wake {
245     my ($msg, $msg_hash, $session_id) = @_ ;
247     foreach (@{$msg_hash->{macAddress}}){
248         &main::daemon_log("INFO: trigger wake for $_", 5);
249         my $host    = $_;
250         my $ipaddr  = '255.255.255.255';
251         my $port    = getservbyname('discard', 'udp');
253         my ($raddr, $them, $proto);
254         my ($hwaddr, $hwaddr_re, $pkt);
256         # get the hardware address (ethernet address)
257         $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
258         if ($host =~ m/^$hwaddr_re$/) {
259                 $hwaddr = $host;
260         } else {
261                 # $host is not a hardware address, try to resolve it
262                 my $ip_re = join('\.', ('([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))') x 4);
263                 my $ip_addr;
264                 if ($host =~ m/^$ip_re$/) {
265                         $ip_addr = $host;
266                 } else {
267                         my $h;
268                         unless ($h = gethost($host)) {
269                                 return undef;
270                         }
271                         $ip_addr = inet_ntoa($h->addr);
272                 }
273         }
275         # Generate magic sequence
276         foreach (split /:/, $hwaddr) {
277                 $pkt .= chr(hex($_));
278         }
279         $pkt = chr(0xFF) x 6 . $pkt x 16;
281         # Allocate socket and send packet
283         $raddr = gethostbyname($ipaddr)->addr;
284         $them = pack_sockaddr_in($port, $raddr);
285         $proto = getprotobyname('udp');
287         socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
288         setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
290         send(S, $pkt, 0, $them) or die "send : $!";
291         close S;
292     }
294     return;
297 1;