package Nmap::Scanner::Backend::Processor; =pod =head1 NAME - Nmap::Scanner::Processor This is the base class for output processors for Nmap::Scanner. =cut use strict; use IPC::Open3; sub new { my $class = shift; my $you = {}; return bless $you, $class; } =pod =head1 register_scan_complete_event() Use this to tell the backend processor you want to be notified when the scan of a HOST is complete. Pass in a reference to a function that will receive two arguments when called: A reference to the calling object and a reference to an Nmap::Scanner::Host instance. =cut sub register_scan_complete_event { $_[0]->{'SCAN_COMPLETE_EVENT'} = $_[1]; } =pod =head1 register_scan_started_event() Use this to tell the backend processor you want to be notified when the scan of a HOST has started. Pass in a reference to a function that will receive two arguments when called: A reference to the calling object and a reference to an Nmap::Scanner::Host instance. =cut sub register_scan_started_event { $_[0]->{'SCAN_STARTED_EVENT'} = $_[1]; } =pod =head1 register_host_closed_event() Use this to tell the backend processor you want to be notified when nmap has determined that the current host is not available (up). Pass in a reference to a function that will receive two arguments when called: A reference to the calling object and a reference to an Nmap::Scanner::Host instance. =cut sub register_host_closed_event { $_[0]->{'HOST_CLOSED_EVENT'} = $_[1]; } =pod =head1 register_port_found_event() Use this to tell the backend processor you want to be notified when an open port has been found on the current host being scanned. Pass in a reference to a function that will receive three arguments when called: A reference to the calling object, a reference to an Nmap::Scanner::Host instance, and a reference to an Nmap::Scanner::Port containing information on the port. =cut sub register_port_found_event { $_[0]->{'PORT_FOUND_EVENT'} = $_[1]; } =pod =head1 register_no_ports_open_event() Use this to tell the backend processor you want to be notified when the scan of a HOST has yielded NO open ports. Pass in a reference to a function that will receive three arguments when called: A reference to the calling object, a reference to an Nmap::Scanner::Host instance, and a reference to an Nmap::Scanner::ExtraPorts instance with some information on the states of the non-open ports. =cut sub register_no_ports_open_event { $_[0]->{'NO_PORTS_OPEN_EVENT'} = $_[1]; } =pod =head1 results() Return the Nmap::Scanner::Results instance created by the scan. =cut sub results { (defined $_[1]) ? ($_[0]->{RESULTS} = $_[1]) : return $_[0]->{RESULTS}; } sub debug { (defined $_[1]) ? ($_[0]->{DEBUG} = $_[1]) : return $_[0]->{DEBUG}; } =pod =head1 start_nmap() This method may be called by the user. It starts the nmap process using the options set by the user via the scan() method or setters of Nmap::Scanner::Scanner. The method returns the PID of the child nmap process, a reader handle to read from the nmap process, a write handle to write to nmap, and an error handle which will contain data if nmap throws an error. Example code: sub process { my $self = shift; my $cmdline = shift; my ($pid, $in, $out, $err) = $self->SUPER::start_nmap($cmdline); # Process filehandles } =cut sub start_nmap { my $self = shift; my $cmdline = shift; local(*READ, *WRITE, *ERROR); my $pid = 0; my $read = *READ; if (-f $cmdline) { open(READ, "+< $cmdline") || die "Can't read from input file $cmdline: $!\n"; *WRITE = *READ; my $error = ""; open(ERROR, '<', \$error); } else { $pid = open3(\*WRITE, \*READ, \*ERROR, $cmdline) || die "Can't open pipe to $cmdline: $!\n"; $read->flush(); } my $write = *WRITE; my $error = *ERROR; return ($pid, $read, $write, $error); } =head1 start_nmap2() This method is called by the sub-classed processor to start the nmap process using options set by the user via the scan() method or setters of Nmap::Scanner::Scanner. The sub-classed processor is returned the PID of the child nmap process and a reader handle to read from the nmap process. Example code: sub process { my $self = shift; my $cmdline = shift; my ($pid, $in) = $self->SUPER::start_nmap2($cmdline); # Process filehandles } =cut sub start_nmap2{ my $self = shift; my $cmdline = shift; local(*READ); my $pid = open(\*READ, "-|", "$cmdline 2>&1"); unless (defined $pid) { die "Can't open pipe to nmap: $!\n"; } my $read = *READ; $read->flush(); return ($pid, $read); } =pod =head1 notify_scan_started() Notify the listener that a scan started event has occurred. Caller is passed a reference to the callers self reference (object instance) and an Nmap::Scanner::Host instance. =cut sub notify_scan_started { &{$_[0]->{'SCAN_STARTED_EVENT'}->[1]}( $_[0]->{'SCAN_STARTED_EVENT'}->[0], $_[1] ) if defined $_[0]->{'SCAN_STARTED_EVENT'}->[1]; } =pod =head1 notify_scan_complete() Notify the listener that a scan complete event has occurred. Caller is passed a reference to the callers self reference (object instance) and an Nmap::Scanner::Host instance. =cut sub notify_scan_complete { &{$_[0]->{'SCAN_COMPLETE_EVENT'}->[1]}( $_[0]->{'SCAN_COMPLETE_EVENT'}->[0], $_[1] ) if (defined $_[0]->{'SCAN_COMPLETE_EVENT'}->[1]); } =pod =head1 notify_scan_started() Notify the listener that a port found event has occurred. Caller is passed a reference to the callers self reference (object instance), an Nmap::Scanner::Host instance, and an Nmap::Scanner::Port instance. =cut sub notify_port_found { &{$_[0]->{'PORT_FOUND_EVENT'}->[1]}( $_[0]->{'PORT_FOUND_EVENT'}->[0], $_[1], $_[2] ) if (defined $_[0]->{'PORT_FOUND_EVENT'}->[1]); } =pod =head1 notify_no_ports_open() Notify the listener that a scan started event has occurred. Caller is passed a reference to the callers self reference (object instance), an Nmap::Scanner::Host instance, and an Nmap::Scanner::ExtraPorts instance. =cut sub notify_no_ports_open { &{$_[0]->{'NO_PORTS_OPEN_EVENT'}->[1]}( $_[0]->{'NO_PORTS_OPEN_EVENT'}->[0], $_[1], $_[2] ) if (defined $_[0]->{'NO_PORTS_OPEN_EVENT'}->[0]); } 1;