6d80ba94459925d65a30d7b29a58b512ffd8cf11
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;
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 },
36 );
37 &read_configfile($main::cfg_file, %cfg_defaults);
40 sub get_events {
41 return \@events;
42 }
45 sub read_configfile {
46 my ($cfg_file, %cfg_defaults) = @_;
47 my $cfg;
49 if( defined( $cfg_file) && ( length($cfg_file) > 0 )) {
50 if( -r $cfg_file ) {
51 $cfg = Config::IniFiles->new( -file => $cfg_file );
52 } else {
53 &main::daemon_log("ERROR: siTriggered.pm couldn't read config file!", 1);
54 }
55 } else {
56 $cfg = Config::IniFiles->new() ;
57 }
58 foreach my $section (keys %cfg_defaults) {
59 foreach my $param (keys %{$cfg_defaults{ $section }}) {
60 my $pinfo = $cfg_defaults{ $section }{ $param };
61 ${@$pinfo[0]} = $cfg->val( $section, $param, @$pinfo[1] );
62 }
63 }
64 }
67 sub reload_ldap_config {
68 my ($msg, $msg_hash, $session_id) = @_;
69 my $header = @{$msg_hash->{header}}[0];
70 my $target = @{$msg_hash->{$header}}[0];
72 my $out_msg = &SIPackages::new_ldap_config($target);
73 my @out_msg_l = ( $out_msg );
74 return @out_msg_l;
75 }
78 sub got_ping {
79 my ($msg, $msg_hash, $session_id) = @_;
81 my $source = @{$msg_hash->{source}}[0];
82 my $target = @{$msg_hash->{target}}[0];
83 my $header = @{$msg_hash->{header}}[0];
84 my $act_time = &get_time;
85 my @out_msg_l;
86 my $out_msg;
88 $session_id = @{$msg_hash->{'session_id'}}[0];
90 # check known_clients_db
91 my $sql_statement = "SELECT * FROM known_clients WHERE hostname='$source'";
92 my $query_res = $main::known_clients_db->select_dbentry( $sql_statement );
93 if( 1 == keys %{$query_res} ) {
94 my $sql_statement= "UPDATE known_clients ".
95 "SET status='$header', timestamp='$act_time' ".
96 "WHERE hostname='$source'";
97 my $res = $main::known_clients_db->update_dbentry( $sql_statement );
98 }
100 # check known_server_db
101 $sql_statement = "SELECT * FROM known_server WHERE hostname='$source'";
102 $query_res = $main::known_server_db->select_dbentry( $sql_statement );
103 if( 1 == keys %{$query_res} ) {
104 my $sql_statement= "UPDATE known_server ".
105 "SET status='$header', timestamp='$act_time' ".
106 "WHERE hostname='$source'";
107 my $res = $main::known_server_db->update_dbentry( $sql_statement );
108 }
110 # create out_msg
111 my $out_hash = &create_xml_hash($header, $source, "GOSA");
112 &add_content2xml_hash($out_hash, "session_id", $session_id);
113 $out_msg = &create_xml_string($out_hash);
114 push(@out_msg_l, $out_msg);
116 return @out_msg_l;
117 }
120 sub detected_hardware {
121 my ($msg, $msg_hash, $session_id) = @_ ;
122 my $address = $msg_hash->{source}[0];
123 my $gotoHardwareChecksum= $msg_hash->{detected_hardware}[0]->{gotoHardwareChecksum};
125 my $sql_statement= "SELECT * FROM known_clients WHERE hostname='$address'";
126 my $res = $main::known_clients_db->select_dbentry( $sql_statement );
128 # check hit
129 my $hit_counter = keys %{$res};
130 if( not $hit_counter == 1 ) {
131 &main::daemon_log("ERROR: more or no hit found in known_clients_db by query by '$address'", 1);
132 return;
133 }
135 my $macaddress = $res->{1}->{macaddress};
136 my $hostkey = $res->{1}->{hostkey};
138 if (not defined $macaddress) {
139 &main::daemon_log("ERROR: no mac address found for client $address", 1);
140 return;
141 }
142 # Build LDAP connection
143 my $ldap = Net::LDAP->new($ldap_uri);
144 if( not defined $ldap ) {
145 &main::daemon_log("ERROR: cannot connect to ldap: $ldap_uri", 1);
146 return;
147 }
149 # Bind to a directory with dn and password
150 my $mesg= $ldap->bind($ldap_admin_dn, password => $ldap_admin_password);
152 # Perform search
153 $mesg = $ldap->search(
154 base => $ldap_base,
155 scope => 'sub',
156 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
157 );
159 # We need to create a base entry first (if not done from ArpHandler)
160 if($mesg->count == 0) {
161 &main::daemon_log("INFO: Need to create a new LDAP Entry for client $address", 6);
162 my $resolver=Net::DNS::Resolver->new;
163 my $ipaddress= $1 if $address =~ /^([0-9\.]*?):.*$/;
164 my $dnsresult= $resolver->search($ipaddress);
165 my $dnsname= (
166 defined($dnsresult) &&
167 defined($dnsresult->{answer} &&
168 defined($dnsresult->{answer}[0] &&
169 defined($dnsresult->{answer}[0]->{ptrdname}
170 )?$dnsresult->{answer}[0]->{ptrdname}:$ipaddress;
171 my $cn = (($dnsname =~ /^(\d){1,3}\.(\d){1,3}\.(\d){1,3}\.(\d){1,3}/) ? $dnsname : sprintf "%s", $dnsname =~ /([^\.]+)\.?/);
172 my $dn = "cn=$cn,ou=incoming,$ldap_base";
173 &main::daemon_log("INFO: Creating entry for $dn",5);
174 my $entry= Net::LDAP::Entry->new( $dn );
175 $entry->dn($dn);
176 $entry->add("objectClass" => "goHard");
177 $entry->add("cn" => $cn);
178 $entry->add("macAddress" => $macaddress);
179 $entry->add("gotomode" => "locked");
180 $entry->add("gotoSysStatus" => "new-system");
181 $entry->add("ipHostNumber" => $ipaddress);
182 if(defined($main::gosa_unit_tag) && length($main::gosa_unit_tag) > 0) {
183 $entry->add("objectClass" => "gosaAdministrativeUnitTag");
184 $entry->add("gosaUnitTag" => $main::gosa_unit_tag);
185 }
186 my $res=$entry->update($ldap);
187 if(defined($res->{'errorMessage'}) &&
188 length($res->{'errorMessage'}) >0) {
189 &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
190 return;
191 } else {
192 # Fill $mesg again
193 $mesg = $ldap->search(
194 base => $ldap_base,
195 scope => 'sub',
196 filter => "(&(objectClass=GOhard)(|(macAddress=$macaddress)(dhcpHWaddress=ethernet $macaddress)))"
197 );
198 }
199 }
201 if($mesg->count == 1) {
202 my $entry= $mesg->entry(0);
203 $entry->changetype("modify");
204 foreach my $attribute (
205 "gotoSndModule", "ghNetNic", "gotoXResolution", "ghSoundAdapter", "ghCpuType", "gotoXkbModel",
206 "ghGfxAdapter", "gotoXMousePort", "ghMemSize", "gotoXMouseType", "ghUsbSupport", "gotoXHsync",
207 "gotoXDriver", "gotoXVsync", "gotoXMonitor", "gotoHardwareChecksum") {
208 if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
209 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
210 if(defined($entry->get_value($attribute))) {
211 $entry->delete($attribute);
212 }
213 &main::daemon_log("INFO: Adding attribute $attribute with value ".$msg_hash->{detected_hardware}[0]->{$attribute},5);
214 $entry->add($attribute => $msg_hash->{detected_hardware}[0]->{$attribute});
215 }
216 }
217 foreach my $attribute (
218 "gotoModules", "ghScsiDev", "ghIdeDev") {
219 if(defined($msg_hash->{detected_hardware}[0]->{$attribute}) &&
220 length($msg_hash->{detected_hardware}[0]->{$attribute}) >0 ) {
221 if(defined($entry->get_value($attribute))) {
222 $entry->delete($attribute);
223 }
224 foreach my $array_entry (@{$msg_hash->{detected_hardware}[0]->{$attribute}}) {
225 $entry->add($attribute => $array_entry);
226 }
227 }
228 }
230 my $res=$entry->update($ldap);
231 if(defined($res->{'errorMessage'}) &&
232 length($res->{'errorMessage'}) >0) {
233 &main::daemon_log("ERROR: can not add entries to LDAP: ".$res->{'errorMessage'}, 1);
234 } else {
235 &main::daemon_log("INFO: Added Hardware configuration to LDAP", 5);
236 }
238 }
239 return ;
240 }
243 sub trigger_wake {
244 my ($msg, $msg_hash, $session_id) = @_ ;
246 foreach (@{$msg_hash->{macAddress}}){
247 &main::daemon_log("INFO: trigger wake for $_", 5);
248 my $host = shift;
249 my $ipaddr = shift || '255.255.255.255';
250 my $port = getservbyname('discard', 'udp');
252 my ($raddr, $them, $proto);
253 my ($hwaddr, $hwaddr_re, $pkt);
255 # get the hardware address (ethernet address)
256 $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
257 if ($host =~ m/^$hwaddr_re$/) {
258 $hwaddr = $host;
259 } else {
260 # $host is not a hardware address, try to resolve it
261 my $ip_re = join('\.', ('([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))') x 4);
262 my $ip_addr;
263 if ($host =~ m/^$ip_re$/) {
264 $ip_addr = $host;
265 } else {
266 my $h;
267 unless ($h = gethost($host)) {
268 return undef;
269 }
270 $ip_addr = inet_ntoa($h->addr);
271 }
272 }
274 # Generate magic sequence
275 foreach (split /:/, $hwaddr) {
276 $pkt .= chr(hex($_));
277 }
278 $pkt = chr(0xFF) x 6 . $pkt x 16;
280 # Allocate socket and send packet
282 $raddr = gethostbyname($ipaddr)->addr;
283 $them = pack_sockaddr_in($port, $raddr);
284 $proto = getprotobyname('udp');
286 socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
287 setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
289 send(S, $pkt, 0, $them) or die "send : $!";
290 close S;
291 }
293 return;
294 }
296 1;