Code

move functions from SIPackages.pm to event module siTriggered.pm
[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     );
9 @EXPORT = @events;
11 use strict;
12 use warnings;
13 use GOSA::GosaSupportDaemon;
14 use Socket;
17 BEGIN {}
19 END {}
21 ### Start ######################################################################
23 my $ldap_uri;
24 my $ldap_base;
25 my $ldap_admin_dn;
26 my $ldap_admin_password;
27 my $gosa_unit_tag;
29 my %cfg_defaults = (
30 "server" => {
31     "ldap-uri" => [\$ldap_uri, ""],
32     "ldap-base" => [\$ldap_base, ""],
33     "ldap-admin-dn" => [\$ldap_admin_dn, ""],
34     "ldap-admin-password" => [\$ldap_admin_password, ""],
35         "gosa-unit-tag" => [\$gosa_unit_tag, ""],
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) && ( length($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 }
67 sub got_ping {
68     my ($msg, $msg_hash, $session_id) = @_;
70     my $source = @{$msg_hash->{source}}[0];
71     my $target = @{$msg_hash->{target}}[0];
72     my $header = @{$msg_hash->{header}}[0];
73     my $act_time = &get_time;
74     my @out_msg_l;
75     my $out_msg;
77     $session_id = @{$msg_hash->{'session_id'}}[0];
79     # check known_clients_db
80     my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source'";
81     my $query_res = $main::known_clients_db->select_dbentry( $sql_statement );
82     if( 1 == keys %{$query_res} ) {
83          my $sql_statement= "UPDATE known_clients ".
84             "SET status='$header', timestamp='$act_time' ".
85             "WHERE hostname='$source'";
86          my $res = $main::known_clients_db->update_dbentry( $sql_statement );
87     } 
88     
89     # check known_server_db
90     $sql_statement = "SELECT * FROM known_server WHERE hostname='$source'";
91     $query_res = $main::known_server_db->select_dbentry( $sql_statement );
92     if( 1 == keys %{$query_res} ) {
93          my $sql_statement= "UPDATE known_server ".
94             "SET status='$header', timestamp='$act_time' ".
95             "WHERE hostname='$source'";
96          my $res = $main::known_server_db->update_dbentry( $sql_statement );
97     } 
99     # create out_msg
100     my $out_hash = &create_xml_hash($header, $source, "GOSA");
101     &add_content2xml_hash($out_hash, "session_id", $session_id);
102     $out_msg = &create_xml_string($out_hash);
103     push(@out_msg_l, $out_msg);
104     
105     return @out_msg_l;
109 sub detected_hardware {
110     my ($msg, $msg_hash, $session_id) = @_ ;
111         my $address = $msg_hash->{source}[0];
112         my $gotoHardwareChecksum= $msg_hash->{detected_hardware}[0]->{gotoHardwareChecksum};
114     my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
115     my $res = $main::known_clients_db->select_dbentry( $sql_statement );
117     # check hit
118     my $hit_counter = keys %{$res};
119     if( not $hit_counter == 1 ) {
120         &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
121                 return;
122     }
124     my $macaddress = $res->{1}->{macaddress};
125     my $hostkey = $res->{1}->{hostkey};
127     if (not defined $macaddress) {
128         &main::daemon_log("ERROR: no mac address found for client $address", 1);
129         return;
130     }
131     # Build LDAP connection
132     my $ldap = Net::LDAP->new($ldap_uri);
133     if( not defined $ldap ) {
134         &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1);
135         return;
136     } 
138     # Bind to a directory with dn and password
139     my $mesg= $ldap->bind($ldap_admin_dn, password => $ldap_admin_password);
141     # Perform search
142         $mesg = $ldap->search(
143                 base   => $ldap_base,
144                 scope  => 'sub',
145                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
146         );
148         # We need to create a base entry first (if not done from ArpHandler)
149         if($mesg->count == 0) {
150                 &main::daemon_log("INFO: Need to create a new LDAP Entry for client $address", 6);
151                 my $resolver=Net::DNS::Resolver->new;
152                 my $ipaddress= $1 if $address =~ /^([0-9\.]*?):.*$/;
153                 my $dnsresult= $resolver->search($ipaddress);
154                 my $dnsname= (defined($dnsresult))?$dnsresult->{answer}[0]->{ptrdname}:$ipaddress;
155                 my $cn = (($dnsname =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/) ? $dnsname : sprintf "%s", $dnsname =~ /([^\.]+)\.?/);
156                 my $dn = "cn=$cn,ou=incoming,$ldap_base";
157                 &main::daemon_log("INFO: Creating entry for $dn",5);
158                 my $entry= Net::LDAP::Entry->new( $dn );
159                 $entry->dn($dn);
160                 $entry->add("objectClass" => "goHard");
161                 $entry->add("cn" => $cn);
162                 $entry->add("macAddress" => $macaddress);
163                 $entry->add("gotomode" => "locked");
164                 $entry->add("gotoSysStatus" => "new-system");
165                 $entry->add("ipHostNumber" => $ipaddress);
166                 if(defined($gosa_unit_tag) && length($gosa_unit_tag) > 0) {
167                         $entry->add("objectClass" => "gosaAdministrativeUnit");
168                         $entry->add("gosaUnitTag" => $gosa_unit_tag);
169                 }
170                 my $res=$entry->update($ldap);
171                 if(defined($res->{'errorMessage'}) &&
172                         length($res->{'errorMessage'}) >0) {
173                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
174                         return;
175                 } else {
176                         # Fill $mesg again
177                         $mesg = $ldap->search(
178                                 base   => $ldap_base,
179                                 scope  => 'sub',
180                                 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
181                         );
182                 }
183         }
184         
185         if($mesg->count == 1) {
186                 my $entry= $mesg->entry(0);
187                 $entry->changetype("modify");
188                 foreach my $attribute (
189                         "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel", 
190                         "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync", 
191                         "gotoXDriver", "gotoXVsync", "gotoXMonitor", "gotoHardwareChecksum") {
192                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
193                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
194                                 if(defined($entry->get_value($attribute))) {
195                                         $entry->delete($attribute);
196                                 }
197                                 &main::daemon_log("INFO: Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},5);
198                                 $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});     
199                         }
200                 }
201                 foreach my $attribute (
202                         "gotoModules", "ghScsiDev", "ghIdeDev") {
203                         if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
204                                 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
205                                 if(defined($entry->get_value($attribute))) {
206                                         $entry->delete($attribute);
207                                 }
208                                 foreach my $array_entry (@{$msg_hash->{detected_hardware}[0]->{$attribute}}) {
209                                         $entry->add($attribute => $array_entry);
210                                 }
211                         }
212                 }
214                 my $res=$entry->update($ldap);
215                 if(defined($res->{'errorMessage'}) &&
216                         length($res->{'errorMessage'}) >0) {
217                         &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
218                 } else {
219                         &main::daemon_log("INFO: Added Hardware configuration to LDAP", 5);
220                 }
222         }
223         return ;
227 sub trigger_wake {
228     my ($msg, $msg_hash, $session_id) = @_ ;
230     foreach (@{$msg_hash->{macAddress}}){
231         &main::daemon_log("INFO: trigger wake for $_", 5);
232         my $host    = shift;
233         my $ipaddr  = shift || '255.255.255.255';
234         my $port    = getservbyname('discard', 'udp');
236         my ($raddr, $them, $proto);
237         my ($hwaddr, $hwaddr_re, $pkt);
239         # get the hardware address (ethernet address)
240         $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
241         if ($host =~ m/^$hwaddr_re$/) {
242                 $hwaddr = $host;
243         } else {
244                 # $host is not a hardware address, try to resolve it
245                 my $ip_re = join('\.', ('([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))') x 4);
246                 my $ip_addr;
247                 if ($host =~ m/^$ip_re$/) {
248                         $ip_addr = $host;
249                 } else {
250                         my $h;
251                         unless ($h = gethost($host)) {
252                                 return undef;
253                         }
254                         $ip_addr = inet_ntoa($h->addr);
255                 }
256         }
258         # Generate magic sequence
259         foreach (split /:/, $hwaddr) {
260                 $pkt .= chr(hex($_));
261         }
262         $pkt = chr(0xFF) x 6 . $pkt x 16;
264         # Allocate socket and send packet
266         $raddr = gethostbyname($ipaddr)->addr;
267         $them = pack_sockaddr_in($port, $raddr);
268         $proto = getprotobyname('udp');
270         socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
271         setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
273         send(S, $pkt, 0, $them) or die "send : $!";
274         close S;
275     }
277     return;
280 1;