summaryrefslogtreecommitdiff
path: root/files/irc_bot/riseup-nagios-server.pl
diff options
context:
space:
mode:
Diffstat (limited to 'files/irc_bot/riseup-nagios-server.pl')
-rw-r--r--files/irc_bot/riseup-nagios-server.pl239
1 files changed, 239 insertions, 0 deletions
diff --git a/files/irc_bot/riseup-nagios-server.pl b/files/irc_bot/riseup-nagios-server.pl
new file mode 100644
index 00000000..5d65e6dd
--- /dev/null
+++ b/files/irc_bot/riseup-nagios-server.pl
@@ -0,0 +1,239 @@
+#!/usr/bin/perl -w
+
+# ##############################################################################
+# a simple IRC bot which dispatches messages received via local domain sockets
+# ##############################################################################
+
+
+######
+## THIS NEEDS TO BE PORTED TO THE NEW FRAMEWORKS!
+##
+## STICKY POINTS: the addfh() function doesn't exist in BasicBot or POE::Component::IRC
+##
+## people suggested we use Anyevent::IRC and POE::Kernel ->select_read and POE::Wheel namespace
+##
+## in the meantime, inspiration for extensions can be found here: http://svn.foswiki.org/trunk/WikiBot/mozbot.pl
+
+use strict;
+use File::Basename;
+
+BEGIN {
+ unshift @INC, dirname($0);
+}
+
+my $VERSION = '0.2';
+my $running = 1;
+
+# Read a configuration file
+# The arg can be a relative or full path, or
+# it can be a file located somewhere in @INC.
+sub ReadCfg
+{
+ my $file = $_[0];
+
+ our $err;
+
+ { # Put config data into a separate namespace
+ package CFG;
+
+ # Process the contents of the config file
+ my $rc = do($file);
+
+ # Check for errors
+ if ($@) {
+ $::err = "ERROR: Failure compiling '$file' - $@";
+ } elsif (! defined($rc)) {
+ $::err = "ERROR: Failure reading '$file' - $!";
+ } elsif (! $rc) {
+ $::err = "ERROR: Failure processing '$file'";
+ }
+ }
+
+ return ($err);
+}
+
+# Get our configuration information
+if (my $err = ReadCfg('/etc/nagios_nsa.cfg')) {
+ print(STDERR $err, "\n");
+ exit(1);
+}
+
+use POSIX qw(setsid);
+use IO::Socket;
+use Net::IRC;
+
+sub new {
+ my $self = {
+ socket => undef,
+ irc => undef,
+ conn => undef,
+ commandfile => undef,
+ };
+
+ return bless($self, __PACKAGE__);
+}
+
+sub daemonize {
+ my $self = shift;
+ my $pid;
+
+ chdir '/' or die "Can't chdir to /: $!";
+
+ open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
+ open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
+
+ defined ($pid = fork) or die "Can't fork: $!";
+
+ if ($pid && $CFG::Nsa{'pidfile'}) { # write pid of child
+ open PID, ">$CFG::Nsa{'pidfile'}" or die "Can't open pid file: $!";
+ print PID $pid;
+ close PID;
+ }
+ exit if $pid;
+ setsid or die "Can't start a new session: $!";
+
+ #open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
+}
+
+sub run {
+ my $self = shift;
+
+ $self->{irc}->do_one_loop();
+}
+
+sub shutdown {
+ my $sig = shift;
+
+ print STDERR "Received SIG$sig, shutting down...\n";
+ $running = 0;
+}
+
+sub socket_has_data {
+ my $self = shift;
+
+ $self->{socket}->recv(my $data, 1024);
+ if ($CFG::Nsa{'usenotices'}) {
+ $self->{conn}->notice($CFG::Nsa{'channel'}, $data);
+ } else {
+ $self->{conn}->privmsg($CFG::Nsa{'channel'}, $data);
+ }
+}
+
+sub irc_on_connect {
+ my $self = shift;
+
+ print STDERR "Joining channel '$CFG::Nsa{'channel'}'...\n";
+ $self->join($CFG::Nsa{'channel'});
+}
+
+sub irc_on_msg {
+ my ($self, $event) = @_;
+ my $data = join(' ', $event->args);
+ #my $nick = quotemeta($nicks[$nick]);
+ my $to = $event->to;
+ #my $channel = &toToChannel($self, @$to);
+ #my $cmdChar = $commandChar{default}; # FIXME: should look up for CURRENT channel first!
+ #if ( exists $commandChar{$channel} ) { $cmdChar = $commandChar{$channel}; }
+ my $msg = parse_msg($event);
+ if (defined($msg)) {
+ #$self->privmsg($event->nick, "alright, sending this message to nagios, hope it figures it out: $msg");
+ } else {
+ $self->privmsg($event->nick, "can't parse $data, you want 'ack host service comment'\n");
+ }
+}
+
+sub irc_on_public {
+ my ($self, $event) = @_;
+ my $data = join(' ', $event->args);
+ my $to = $event->to;
+ if ($data =~ s/([^:]*):\s+//) {
+ if ($1 eq $CFG::Nsa{'nickname'}) {
+ my $msg = parse_msg($event);
+ if (defined($msg)) {
+ #$self->privmsg($event->to, "alright, sending this message to nagios, hope it figures it out: $msg");
+ } else {
+ $self->privmsg($event->to, "can't parse $data, you want 'ack host service comment'\n");
+ }
+ } else {
+ #print STDERR "ignoring message $data, not for me (me being $1)\n";
+ }
+ } else {
+ #print STDERR "ignoring message $data\n";
+ }
+}
+
+sub parse_msg {
+ my $event= shift;
+ my $data = join(' ', $event->args);
+ my $msg;
+ if ($data =~ m/([^:]*:)?\s*ack(?:knowledge)?\s+([a-zA-Z0-9\-\.]+)(?:\s+([-\w\.]+)(?:\s+([\w\s]+))?)?/) {
+ #print STDERR "writing to nagios scoket ". $CFG::Nsa{'commandfile'} . "\n";
+ open(my $cmdfile, ">", $CFG::Nsa{'commandfile'}) || die "Can't open Nagios commandfile: $CFG::Nsa{'commandfile'}!\n";
+ my $host = $2;
+ my ($service, $comment) = (undef, "no comment (from irc)");
+ if ($4) {
+ $service = $3;
+ $comment = $4;
+ } elsif ($3) {
+ $service = $3;
+ }
+ my $user = $event->nick;
+ $msg = '[' . time() . '] ';
+ if (defined($service)) {
+ $msg .= "ACKNOWLEDGE_SVC_PROBLEM;$host;$service;1;1;1;$user;$comment\n";
+ } else {
+ $msg .= "ACKNOWLEDGE_HOST_PROBLEM;$host;1;1;1;$user;$comment\n";
+ }
+ print {$cmdfile} $msg;
+ close($cmdfile);
+ }
+ return $msg;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+my $bot = &new;
+
+if (-e $CFG::Nsa{'socket'}) {
+ die "Socket '$CFG::Nsa{'socket'}' exists!\n";
+}
+
+$bot->{socket} = IO::Socket::UNIX->new (
+ Local => $CFG::Nsa{'socket'},
+ Type => SOCK_DGRAM,
+ Listen => 5
+) || die "Can't create socket '$CFG::Nsa{'socket'}'!\n";
+
+$SIG{INT} = $SIG{TERM} = \&shutdown;
+
+$bot->daemonize();
+$bot->{irc} = new Net::IRC;
+
+$bot->{conn} = $bot->{irc}->newconn (
+ Server => $CFG::Nsa{'server'},
+ Port => $CFG::Nsa{'port'},
+ Nick => $CFG::Nsa{'nickname'},
+ Username => $CFG::Nsa{'nickname'},
+ Password => $CFG::Nsa{'password'},
+ Ircname => $CFG::Nsa{'realname'} . " (NSA $VERSION)",
+) || die "Can't connect to server '$CFG::Nsa{'server'}'!\n";
+
+$bot->{conn}->add_global_handler(376, \&irc_on_connect);
+$bot->{conn}->add_global_handler('nomotd', \&irc_on_connect);
+$bot->{conn}->add_global_handler('msg', \&irc_on_msg);
+$bot->{conn}->add_global_handler('public', \&irc_on_public);
+#$bot->{conn}->add_global_handler('notice', \&irc_on_msg);
+$bot->{irc}->addfh($bot->{socket}, \&socket_has_data, 'r', $bot);
+
+while ($running) {
+ $bot->run();
+}
+
+close($bot->{socket});
+unlink($CFG::Nsa{'socket'});
+
+exit(0);
+
+1;
+
+__END__