Code

Added simple locale extractor
[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;
18 BEGIN {}
20 END {}
22 ### Start ######################################################################
24 my $ldap_uri;
25 my $ldap_base;
26 my $ldap_admin_dn;
27 my $ldap_admin_password;
28 my $mesg;
30 my %cfg_defaults = (
31 "server" => {
32     "ldap-uri" => [\$ldap_uri, ""],
33     "ldap-base" => [\$ldap_base, ""],
34     "ldap-admin-dn" => [\$ldap_admin_dn, ""],
35     "ldap-admin-password" => [\$ldap_admin_password, ""],
36     },
37 );
38 &read_configfile($main::cfg_file, %cfg_defaults);
41 sub get_events {
42     return \@events;
43 }
46 sub read_configfile {
47     my ($cfg_file, %cfg_defaults) = @_;
48     my $cfg;
50     if( defined( $cfg_file) && ( (-s $cfg_file) > 0 )) {
51         if( -r $cfg_file ) {
52             $cfg = Config::IniFiles->new( -file => $cfg_file );
53         } else {
54             &main::daemon_log("ERROR: siTriggered.pm couldn't read config file!", 1);
55         }
56     } else {
57         $cfg = Config::IniFiles->new() ;
58     }
59     foreach my $section (keys %cfg_defaults) {
60         foreach my $param (keys %{$cfg_defaults{ $section }}) {
61             my $pinfo = $cfg_defaults{ $section }{ $param };
62             ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
63         }
64     }
65 }
68 sub reload_ldap_config {
69     my ($msg, $msg_hash, $session_id) = @_;
70     my $header = @{$msg_hash->{header}}[0];
71     my $target = @{$msg_hash->{$header}}[0];
73     my $out_msg = &ClientPackages::new_ldap_config($target, $session_id);
74     my @out_msg_l = ( $out_msg );
75     return @out_msg_l;
76 }
79 sub got_ping {
80     my ($msg, $msg_hash, $session_id) = @_;
82     my $source = @{$msg_hash->{source}}[0];
83     my $target = @{$msg_hash->{target}}[0];
84     my $header = @{$msg_hash->{header}}[0];
85     my $act_time = &get_time;
86     my @out_msg_l;
87     my $out_msg;
89     $session_id = @{$msg_hash->{'session_id'}}[0];
91     # check known_clients_db
92     my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source'";
93     my $query_res = $main::known_clients_db->select_dbentry( $sql_statement );
94     if( 1 == keys %{$query_res} ) {
95          my $sql_statement= "UPDATE known_clients ".
96             "SET status='$header', timestamp='$act_time' ".
97             "WHERE hostname='$source'";
98          my $res = $main::known_clients_db->update_dbentry( $sql_statement );
99     } 
100     
101     # check known_server_db
102     $sql_statement = "SELECT * FROM known_server WHERE hostname='$source'";
103     $query_res = $main::known_server_db->select_dbentry( $sql_statement );
104     if( 1 == keys %{$query_res} ) {
105          my $sql_statement= "UPDATE known_server ".
106             "SET status='$header', timestamp='$act_time' ".
107             "WHERE hostname='$source'";
108          my $res = $main::known_server_db->update_dbentry( $sql_statement );
109     } 
111     # create out_msg
112     my $out_hash = &create_xml_hash($header, $source, "GOSA");
113     &add_content2xml_hash($out_hash, "session_id", $session_id);
114     $out_msg = &create_xml_string($out_hash);
115     my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0];
116     if (defined $forward_to_gosa) {
117         $out_msg =~s/<\/xml>/<forward_to_gosa>$forward_to_gosa<\/forward_to_gosa><\/xml>/;
118     }
119     push(@out_msg_l, $out_msg);
120     
121     return @out_msg_l;
125 sub detected_hardware {
126         my ($msg, $msg_hash, $session_id) = @_ ;
127         my $address = $msg_hash->{source}[0];
128         my $header = $msg_hash->{header}[0];
129         my $gotoHardwareChecksum= $msg_hash->{detected_hardware}[0]->{gotoHardwareChecksum};
131         my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
132         my $res = $main::known_clients_db->select_dbentry( $sql_statement );
134         # check hit
135         my $hit_counter = keys %{$res};
136         if( not $hit_counter == 1 ) {
137                 &main::daemon_log("$session_id ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
138                 return;
139         }
141         my $macaddress = $res->{1}->{macaddress};
142         my $hostkey = $res->{1}->{hostkey};
144         if (not defined $macaddress) {
145                 &main::daemon_log("$session_id ERROR: no mac address found for client $address", 1);
146                 return;
147         }
148         # Build LDAP connection
149   my $ldap_handle = &main::get_ldap_handle($session_id);
150         if( not defined $ldap_handle ) {
151                 &main::daemon_log("$session_id ERROR: cannot connect to ldap: $ldap_uri", 1);
152                 return;
153         } 
155         # Perform search
156         $mesg = $ldap_handle->search(
157                 base   => $ldap_base,
158                 scope  => 'sub',
159                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
160         );
162         # We need to create a base entry first (if not done from ArpHandler)
163         if($mesg->count == 0) {
164                 &main::daemon_log("INFO: Need to create a new LDAP Entry for client $address", 4);
165                 my $ipaddress= $1 if $address =~ /^([0-9\.]*?):.*$/;
166                 my $dnsname;
167                 if (defined($msg_hash->{'force-hostname'}) && 
168                         defined($msg_hash->{'force-hostname'}[0]) &&
169                         length($msg_hash->{'force-hostname'}[0]) > 0){
170                         $dnsname= $msg_hash->{'force-hostname'}[0];
171                         &main::daemon_log("INFO: Using forced hostname $dnsname for client $address", 4);
172                 } else {
173                         $dnsname= gethostbyaddr(inet_aton($ipaddress), AF_INET) || $ipaddress;
174                 }
176                 my $cn = (($dnsname =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/) ? $dnsname : sprintf "%s", $dnsname =~ /([^\.]+)\.?/);
177                 my $dn = "cn=$cn,ou=incoming,$ldap_base";
178                 &main::daemon_log("INFO: Creating entry for $dn",5);
179                 my $entry= Net::LDAP::Entry->new( $dn );
180                 $entry->dn($dn);
181                 $entry->add("objectClass" => "goHard");
182                 $entry->add("cn" => $cn);
183                 $entry->add("macAddress" => $macaddress);
184                 $entry->add("gotomode" => "locked");
185                 $entry->add("gotoSysStatus" => "new-system");
186                 $entry->add("ipHostNumber" => $ipaddress);
187                 if(defined($main::gosa_unit_tag) && length($main::gosa_unit_tag) > 0) {
188                         $entry->add("objectClass" => "gosaAdministrativeUnitTag");
189                         $entry->add("gosaUnitTag" => $main::gosa_unit_tag);
190                 }
191                 my $res=$entry->update($ldap_handle);
192                 if(defined($res->{'errorMessage'}) &&
193                         length($res->{'errorMessage'}) >0) {
194                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
195                         return;
196                 } else {
197                         # Fill $mesg again
198                         $mesg = $ldap_handle->search(
199                                 base   => $ldap_base,
200                                 scope  => 'sub',
201                                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
202                         );
203                 }
204         }
206         if($mesg->count == 1) {
207                 my $entry= $mesg->entry(0);
208                 $entry->changetype("modify");
209                 foreach my $attribute (
210                         "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel", 
211                         "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync", 
212                         "gotoXDriver", "gotoXVsync", "gotoXMonitor", "gotoHardwareChecksum") {
213                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
214                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
215                                 if(defined($entry->get_value($attribute))) {
216                                         $entry->delete($attribute => []);
217                                 }
218                                 &main::daemon_log("INFO: Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},5);
219                                 $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});     
220                         }
221                 }
222                 foreach my $attribute (
223                         "gotoModules", "ghScsiDev", "ghIdeDev") {
224                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
225                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
226                                 if(defined($entry->get_value($attribute))) {
227                                         $entry->delete($attribute => []);
228                                 }
229                                 foreach my $array_entry (keys %{{map { $_ => 1 } sort(@{$msg_hash->{detected_hardware}[0]->{$attribute}}) }}) {
230                                         $entry->add($attribute => $array_entry);
231                                 }
232                         }
233                 }
235                 my $res=$entry->update($ldap_handle);
236                 if(defined($res->{'errorMessage'}) &&
237                         length($res->{'errorMessage'}) >0) {
238                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
239                 } else {
240                         &main::daemon_log("INFO: Added Hardware configuration to LDAP", 5);
241                 }
242         }
244         # if there is a job in job queue for this host and this macaddress, delete it, cause its no longer used
245         my $del_sql = "DELETE FROM $main::job_queue_tn WHERE (macaddress='$macaddress' AND headertag='$header')";
246         my $del_res = $main::job_db->exec_statement($del_sql);
248         return ;
252 sub trigger_wake {
253     my ($msg, $msg_hash, $session_id) = @_ ;
255     foreach (@{$msg_hash->{macAddress}}){
256         &main::daemon_log("$session_id INFO: trigger wake for $_", 5);
257         my $host    = $_;
258         my $ipaddr  = '255.255.255.255';
259         my $port    = getservbyname('discard', 'udp');
261         my ($raddr, $them, $proto);
262         my ($hwaddr, $hwaddr_re, $pkt);
264         # get the hardware address (ethernet address)
265         $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
266         if ($host =~ m/^$hwaddr_re$/) {
267           $hwaddr = $host;
268         } else {
269           &main::daemon_log("$session_id ERROR: trigger_wake called with non mac address", 1);
270         }
272         # Generate magic sequence
273         foreach (split /:/, $hwaddr) {
274                 $pkt .= chr(hex($_));
275         }
276         $pkt = chr(0xFF) x 6 . $pkt x 16;
278         # Allocate socket and send packet
280         $raddr = gethostbyname($ipaddr);
281         $them = pack_sockaddr_in($port, $raddr);
282         $proto = getprotobyname('udp');
284         socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
285         setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
287         send(S, $pkt, 0, $them) or die "send : $!";
288         close S;
289     }
291     return;
294 1;