From 2092adfdbc62ee3fb431ce458d4e5dc4ad57d80f Mon Sep 17 00:00:00 2001 From: "Zane C. Bowers-Hadley" Date: Tue, 19 Feb 2019 03:18:16 -0600 Subject: [PATCH] setting and setting fetching done... time to implement actual logic --- .../lib/Parse/Netstat/Search.pm | 266 +++++++++++++++++- 1 file changed, 258 insertions(+), 8 deletions(-) diff --git a/Parse-Netstat-Search/lib/Parse/Netstat/Search.pm b/Parse-Netstat-Search/lib/Parse/Netstat/Search.pm index 92add33..e7a87ee 100644 --- a/Parse-Netstat-Search/lib/Parse/Netstat/Search.pm +++ b/Parse-Netstat-Search/lib/Parse/Netstat/Search.pm @@ -3,10 +3,12 @@ package Parse::Netstat::Search; use 5.006; use strict; use warnings; +use base 'Error::Helper'; +use Net::CIDR; =head1 NAME -Parse::Netstat::Search - Searches +Parse::Netstat::Search - Searches the connection list in the hash returned by Parse::Netstat =head1 VERSION @@ -19,15 +21,16 @@ our $VERSION = '0.0.0'; =head1 SYNOPSIS -Quick summary of what the module does. - -Perhaps a little code snippet. use Parse::Netstat::Search; + use Parse::Netstat qw(parse_netstat); + + my $res = parse_netstat(output => join("", `netstat -anp`), flavor=>'linux'); my $search = Parse::Netstat::Search->new(); + =head1 methods =head2 new @@ -35,6 +38,22 @@ Perhaps a little code snippet. =cut sub new{ + my $self={ + perror=>undef, + error=>undef, + errorString=>'', + errorExtra=>{ + '1'=>'badCIDR', + '2' =>'unknownService', + }, + cidrs=>[], + protocols=>{}, + ports=>{}, + states=>{}, + }; + bless $self; + + return $self; } @@ -46,8 +65,35 @@ The returned value is an array. =cut -sub get_cidr{ +sub get_cidrs{ + my $self=$_[0]; + if( ! $self->errorblank ){ + return undef; + } + + return @{ $self->{cidrs} }; +} + +=head2 get_ports + +Gets a list of desired ports. + +The returned value is a array. Each item is a port number, +regardless of if it was set based on number or service name. + + my @ports=$search->get_ports; + +=cut + +sub get_ports{ + my $self=$_[0]; + + if( ! $self->errorblank ){ + return undef; + } + + return keys( %{ $self->{ports} } ); } =head2 get_protocols @@ -59,7 +105,13 @@ The returned value is a array. =cut sub get_protocols{ + my $self=$_[0]; + if( ! $self->errorblank ){ + return undef; + } + + return keys( %{ $self->{protocols} } ); } =head2 get_states @@ -71,7 +123,13 @@ The returned value is a array. =cut sub get_states{ + my $self=$_[0]; + if( ! $self->errorblank ){ + return undef; + } + + return keys( %{ $self->{states} } ); } =head2 set_cidrs @@ -79,14 +137,53 @@ sub get_states{ This sets the list of CIDRs to search for in either the local or remote field. -One value is taken and that is a array of CIDRs. +One value is taken and that is a array ref of CIDRs. Validating in is done by Net::CIDR::cidrvalidate. + # set the desired CIDRs to the contents of @CIDRs + $search->set_cidrs( \@CIDRs ); + if ( $search->error ){ + warn("Improper CIDR"); + } + + # clear any previously set + $search->set_cidrs; + =cut sub set_cidrs{ + my $self=$_[0]; + my @cidrs; + if ( defined( $_ ) ){ + @cidrs=@{ $_[1] }; + } + if( ! $self->errorblank ){ + return undef; + } + + #blank it if none is given + if ( !defined( $cidrs[0] ) ){ + $self->{cidrs}=\@cidrs; + } + + #chueck each one + my $cidr=pop(@cidrs); + while ( defined( $cidr ) ){ + if ( ! Net::CIDR::cidrvalidate( $cidr ) ){ + $self->{error}=1; + $self->{errorString}='"'.$cidr.'" is not a valid CIDR according to Net::CIDR::cidrvalidate'; + $self->warn; + return undef; + } + + $cidr=pop(@cidrs); + } + + $self->{cidrs}=\@cidrs; + + return 1; } =head2 set_ports @@ -94,14 +191,66 @@ sub set_cidrs{ This sets the ports to search for in either the local or remote field. -One value is taken and that is a array of ports. +One value is taken and that is a array ref of ports. + +The ports can be either numeric or by name. + + # Set the desired ports to the contents of @ports. + $search->set_ports( \@ports ); + if ( $search->error ){ + warn("Bad value in ports array"); + } + + # removes any previous selections + $search->set_ports; =cut sub set_ports{ + my $self=$_[0]; + my @ports; + if ( defined( $_ ) ){ + @ports=@{ $_[1] }; + } + if( ! $self->errorblank ){ + return undef; + } + + if ( !defined( $ports[0] ) ){ + $self->{ports}={}; + } + + my $port=pop( @ports ); + my %lookup_hash; + while( defined( $port ) ){ + my $port_number; + if ( $port =~ /^\d+$/ ){ + # Find the first matching port number. + # Does not care what protocol comes up. + $port_number=(getservbyname( $port , '' ))[2]; + + # If it is not defined, we did not find a matching + # service record for the requested port name. + if ( !defined( $port_number ) ){ + $self->{error}=2; + $self->{errorString}='"'.$port.'" was not found as a known service'; + $self->warn; + return undef; + } + } + + $lookup_hash{$port_number}=1; + + $port=pop( @ports ); + } + + #save this for later + $self->{ports}=\%lookup_hash; + + return 1; } - + =head2 set_protocols Sets the list of desired protocols to match. @@ -110,10 +259,54 @@ One value is taken and that is a array. If this is undef, then previous settings will be cleared. +Lacking of exhaustive list of possible values for the +OSes supported by Parse::Netstat, no santity checking +is done. + +Starting and trailing white space is removed. + + # Set the desired ports to the contents of @protocols. + $search->set_protocols( \@protocols ); + if ( $search->error ){ + warn("Bad value in ports array"); + } + + # removes any previous selections + $search->set_protocols; + =cut sub set_protocols{ + my $self=$_[0]; + my @protocols; + if ( defined( $_ ) ){ + @protocols=@{ $_[1] }; + } + if( ! $self->errorblank ){ + return undef; + } + + if ( !defined( $protocols[0] ) ){ + $self->{protocols}={}; + } + + my %lookup_hash; + my $protocol=pop( @protocols ); + while( defined( $protocol ) ){ + $protocol=~s/^[\ \t]*//; + $protocol=~s/^[\ \t]*//; + + #create a LCed version of the protocol name + $lookup_hash{ lc( $protocol ) }=1; + + $protocol=pop( @protocols ); + } + + #save it for usage later + $self->{protocols}=\%lookup_hash; + + return 1; } =head2 set_states @@ -124,13 +317,70 @@ One value is taken and that is a array. If this is undef, then previous settings will be cleared. +Lacking of exhaustive list of possible values for the +OSes supported by Parse::Netstat, no santity checking +is done. + +Starting and trailing white space is removed. + + # Set the desired ports to the contents of @protocols. + $search->set_protocols( \@protocols ); + if ( $search->error ){ + warn("Bad value in ports array"); + } + + # removes any previous selections + $search->set_protocols; =cut sub set_states{ + my $self=$_[0]; + my @states; + if ( defined( $_ ) ){ + @states=@{ $_[1] }; + } + if( ! $self->errorblank ){ + return undef; + } + + if ( !defined( $states[0] ) ){ + $self->{staes}={}; + } + + my %lookup_hash; + my $state=pop(@states); + while ( defined( $state ) ){ + $state=~s/^[\ \t]*//; + $state=~s/^[\ \t]*//; + + #create a LCed version of the protocol name + $lookup_hash{ lc( $state ) }=1; + + $state=pop(@states); + } + + #save it for usage later + $self->{states}=\%lookup_hash; + + return 1; } +=head1 ERROR CODES / FLAGS + +Error handling is provided by L. + +=head2 1 / badCIDR + +Invalid CIDR passed. + +Validation is done by Net::CIDR::cidrvalidate. + +=head2 2 / unknownService + +Could not look up the port number for the specified service. + =head1 AUTHOR Zane C. Bowers-Hadley, C<< >>