| 2 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 3 |  | # ----------------------------------------------------------- | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 4 |  | # Perl i-scream Host. | 
 
 
 
 
 
 
 
 | 5 | + | # http://www.i-scream.org.uk | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 6 |  | # | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 7 |  | # An all-in-one script to act as an i-scream host on | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 8 |  | # a typical Unix/Linux box.  You may adapt the data-gathering | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 72 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 73 |  | exit(0); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 74 |  |  | 
 
 
 
 
 
 
 
 | 75 | + |  | 
 
 
 
 
 
 
 
 | 76 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 | 77 | + | # tcp_configure | 
 
 
 
 
 
 
 
 | 78 | + | # Establishes a TCP connection to the specified i-scream filter manager. | 
 
 
 
 
 
 
 
 | 79 | + | # The host then requests details from the server, such as the intervals | 
 
 
 
 
 
 
 
 | 80 | + | # at which to send UDP packets. | 
 
 
 
 
 
 
 
 | 81 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 82 |  | sub tcp_configure() { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 83 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 84 |  | my($sock) = new IO::Socket::INET( | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 85 |  | PeerAddr => $filter_manager_addr, | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 86 |  | PeerPort => $filter_manager_port, | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 87 |  | Proto => 'tcp' | 
 
 
 
 
 
 
 
 
 
 
 | 88 | < | ) or die "Could not perform configuration via TCP: $!\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 88 | > | ); | 
 
 
 
 
 | 89 | > | if (!defined $sock) { | 
 
 
 
 
 | 90 | > | print "IHOST ERROR: Could not connect to $filter_manager_addr:$filter_manager_port.\n"; | 
 
 
 
 
 | 91 | > | print "Please check that there is an i-scream server at this address.\n"; | 
 
 
 
 
 | 92 | > | print "Program ended.\n"; | 
 
 
 
 
 | 93 | > | exit(1); | 
 
 
 
 
 | 94 | > | } | 
 
 
 
 
 
 
 
 
 
 
 | 95 |  |  | 
 
 
 
 
 
 
 
 
 
 
 | 96 | < | die "Could not connect to the i-scream filter manager: $!\n" unless $sock; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 83 | < |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 84 | < | # Now run through the configuration process. | 
 
 
 
 
 
 
 
 
 | 96 | > | # Now run through the configuration process... | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 97 |  | my($response); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 98 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 99 |  | print $sock "STARTCONFIG\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 163 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 164 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 165 |  | print "Configuration finished sucessfully!\n"; | 
 
 
 
 
 
 
 
 | 166 | + |  | 
 
 
 
 
 
 
 
 | 167 | + | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 168 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 169 |  |  | 
 
 
 
 
 
 
 
 | 170 | + |  | 
 
 
 
 
 
 
 
 | 171 | + |  | 
 
 
 
 
 
 
 
 | 172 | + |  | 
 
 
 
 
 
 
 
 | 173 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 | 174 | + | # send_udp_packet | 
 
 
 
 
 
 
 
 | 175 | + | # Sends a UDP packet to an i-scream filter. | 
 
 
 
 
 
 
 
 | 176 | + | # The packet contains XML markup describing some of the machine's state. | 
 
 
 
 
 
 
 
 | 177 | + | # Receipt of UDP packets is not guaranteed. | 
 
 
 
 
 
 
 
 | 178 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 179 |  | sub send_udp_packet() { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 180 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 181 |  | my(@statgrab) = `./statgrab.pl`; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 182 |  | my(%packet); | 
 
 
 
 
 
 
 
 
 
 
 | 183 | < | for (my($i) = 0; $i < $#statgrab; $i++) { | 
 
 
 
 
 
 
 
 
 | 183 | > | for (my($i) = 0; $i <= $#statgrab; $i++) { | 
 
 
 
 
 
 
 
 
 
 
 | 184 |  | $statgrab[$i] =~ /^([^\s]*) (.*)$/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 185 |  | $packet{$1} = $2; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 186 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 190 |  | my($disk_info) = "<disk>"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 191 |  | my($i) = 0; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 192 |  | while (defined $packet{"packet.disk.p$i.attributes.mount"}) { | 
 
 
 
 
 
 
 
 
 
 
 | 193 | < | $disk_info .= "<p$i>"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 194 | < | $disk_info .= qq/<name>$packet{"packet.disk.p$i.attributes.name"}<\/name>/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 195 | < | $disk_info .= qq/<kbytes>$packet{"packet.disk.p$i.attributes.kbytes"}<\/kbytes>/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 196 | < | $disk_info .= qq/<used>$packet{"packet.disk.p$i.attributes.used"}<\/used>/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 197 | < | $disk_info .= qq/<avail>$packet{"packet.disk.p$i.attributes.avail"}<\/avail>/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 198 | < | $disk_info .= qq/<mount>$packet{"packet.disk.p$i.attributes.mount"}<\/mount>/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 199 | < | $disk_info .= "</p$i>"; | 
 
 
 
 
 
 
 
 
 | 193 | > | $disk_info .= "<p$i"; | 
 
 
 
 
 | 194 | > | $disk_info .= " name=\"" . $packet{"packet.disk.p$i.attributes.name"} . "\""; | 
 
 
 
 
 | 195 | > | $disk_info .= " kbytes=\"" . $packet{"packet.disk.p$i.attributes.kbytes"} . "\""; | 
 
 
 
 
 | 196 | > | $disk_info .= " used=\"" . $packet{"packet.disk.p$i.attributes.used"} . "\""; | 
 
 
 
 
 | 197 | > | $disk_info .= " avail=\"" . $packet{"packet.disk.p$i.attributes.avail"} . "\""; | 
 
 
 
 
 | 198 | > | $disk_info .= " mount=\"" . $packet{"packet.disk.p$i.attributes.mount"} . "\""; | 
 
 
 
 
 | 199 | > | $disk_info .= "></p$i>"; | 
 
 
 
 
 
 
 
 
 
 
 | 200 |  | ++$i; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 201 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 202 |  | $disk_info .= "</disk>"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 203 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 204 |  | my($hostname) = hostname(); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 205 |  | $hostname =~ s/\..*$//g; | 
 
 
 
 
 
 
 
 
 
 
 | 206 | < | `cat /etc/resolv.conf` =~ /domain\s+([^\s]+)/; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 207 | < | my($domainname) = $1; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 208 | < | my($machine_name) = "$hostname.$domainname"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 206 | > | my($resolv) = `cat /etc/resolv.conf`; | 
 
 
 
 
 | 207 | > | my($domainname); | 
 
 
 
 
 | 208 | > | my($machine_name); | 
 
 
 
 
 | 209 | > | if($resolv =~ /domain\s+([^\s]+)/) { | 
 
 
 
 
 | 210 | > | # some machines have domain <domain> in resolv.conf | 
 
 
 
 
 | 211 | > | $domainname = $1; | 
 
 
 
 
 | 212 | > | $machine_name = "$hostname.$domainname"; | 
 
 
 
 
 | 213 | > | } | 
 
 
 
 
 | 214 | > | elsif($resolv =~ /search\s+([^\s]+)/) { | 
 
 
 
 
 | 215 | > | # some machines have search <domain> in resolv.conf | 
 
 
 
 
 | 216 | > | $domainname = $1; | 
 
 
 
 
 | 217 | > | $machine_name = "$hostname.$domainname"; | 
 
 
 
 
 | 218 | > | } | 
 
 
 
 
 | 219 | > | else { | 
 
 
 
 
 | 220 | > | # we can't find out the domain | 
 
 
 
 
 | 221 | > | $machine_name = $hostname; | 
 
 
 
 
 | 222 | > | } | 
 
 
 
 
 
 
 
 
 
 
 | 223 |  | my($ip) = inet_ntoa(scalar(gethostbyname($hostname)) || 'localhost'); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 224 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 225 |  | # Build the XML packet this way, as we can clearly | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 226 |  | # see the structure and contents... I like this ;-) | 
 
 
 
 
 
 
 
 | 227 | + | # [Note that the server rejects UDP packets that are | 
 
 
 
 
 
 
 
 | 228 | + | # larger than 8196 bytes] | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 229 |  | my($xml) = <<EOF; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 230 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 231 |  | <packet seq_no="$seq_no" machine_name="$machine_name" date="$date" type="data" ip="$ip"> | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 261 |  | <swap>$packet{"packet.cpu.swap"}</swap> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 262 |  | </cpu> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 263 |  | <memory> | 
 
 
 
 
 
 
 
 
 
 
 | 264 | < | <total>$packet{"packet.memory.real"}</total> | 
 
 
 
 
 
 
 
 
 | 264 | > | <total>$packet{"packet.memory.total"}</total> | 
 
 
 
 
 
 
 
 
 
 
 | 265 |  | <free>$packet{"packet.memory.free"}</free> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 266 |  | </memory> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 267 |  | <swap> | 
 
 
 
 
 
 
 
 
 
 
 | 268 | < | <total>$packet{"packet.memory.swap_total"}</total> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 269 | < | <free>$packet{"packet.memory.swap_free"}</free> | 
 
 
 
 
 
 
 
 
 | 268 | > | <total>$packet{"packet.swap.total"}</total> | 
 
 
 
 
 | 269 | > | <free>$packet{"packet.swap.free"}</free> | 
 
 
 
 
 
 
 
 
 
 
 | 270 |  | </swap> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 271 |  | $disk_info | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 272 |  | </packet> | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 273 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 274 |  | EOF | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 275 |  |  | 
 
 
 
 
 
 
 
 | 276 | + | # Make the packet smaller by stripping out newlines and leading spaces. | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 277 |  | $xml =~ s/\n\s*//g; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 278 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 279 |  | my($sock) = new IO::Socket::INET ( | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 286 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 287 |  | $seq_no++; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 288 |  | print "-"; | 
 
 
 
 
 
 
 
 | 289 | + |  | 
 
 
 
 
 
 
 
 | 290 | + | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 291 |  | } | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 292 |  |  | 
 
 
 
 
 
 
 
 | 293 | + |  | 
 
 
 
 
 
 
 
 | 294 | + |  | 
 
 
 
 
 
 
 
 | 295 | + |  | 
 
 
 
 
 
 
 
 | 296 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 | 297 | + | # send_tcp_heartbeat | 
 
 
 
 
 
 
 
 | 298 | + | # Establishes a TCP connection to an i-scream filter. | 
 
 
 
 
 
 
 
 | 299 | + | # The heartbeat is used as a guaranteed "I'm alive" delivery mechanism. | 
 
 
 
 
 
 
 
 | 300 | + | #----------------------------------------------------------------------- | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 301 |  | sub send_tcp_heartbeat() { | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 302 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 303 |  | my($sock) = new IO::Socket::INET( | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 304 |  | PeerAddr => $filter_addr, | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 305 |  | PeerPort => $tcp_port, | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 306 |  | Proto => 'tcp' | 
 
 
 
 
 
 
 
 
 
 
 | 307 | < | ) or die "Could not perform heartbeat via TCP: $!\n"; | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 307 | > | ); | 
 
 
 
 
 | 308 | > | if (!defined $sock) { | 
 
 
 
 
 | 309 | > | print "IHOST WARNING: Failed to deliver a heartbeat to the i-scream filter.\n"; | 
 
 
 
 
 | 310 | > | return; | 
 
 
 
 
 | 311 | > | } | 
 
 
 
 
 
 
 
 
 
 
 | 312 |  |  | 
 
 
 
 
 
 
 
 
 | 259 | – | die "Could not connect to the i-scream filter: $!\n" unless $sock; | 
 
 
 
 
 
 
 
 
 | 260 | – |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 313 |  | # Now run through the configuration process. | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 314 |  | my($response); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 315 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 | 365 |  |  | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 366 |  | close($sock); | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 367 |  | print "^"; | 
 
 
 
 
 
 
 
 | 368 | + |  | 
 
 
 
 
 
 
 
 | 369 | + | return; | 
 
 
 
 
 
 
 
 
 
 
 
 
 | 370 |  | } |