/usr/local/CPAN/Authen-Tcpdmatch/Authen/Tcpdmatch/Grammar.pm


# Copyright (c) 2003 Ioannis Tambouras <ioannis@earthlink.net> .
# All rights reserved.
 
package  Authen::Tcpdmatch::Grammar;

use strict;
use Attribute::Handlers;
use Parse::RecDescent;
use warnings;



$Parse::RecDescent::skip = '[, \t]*' ;



our $grammar = q(
                { use NetAddr::IP; no strict 'refs'}
                { our ( $found, $e, $side, $remote, $service, $OK_remote, $OK_service)             }
		{ sub found     { $OK_service && $OK_remote  or  undef                             }}
		{ sub init      { ($service, $remote)=@_; @_= $OK_remote = $OK_service = $found = undef}}
		{ sub register  { ${"OK_$side"} = !$e}                                             }
                { sub tally     { register    if  $_[0] eq ${"$side"}                              }}
		{ sub dot_host  { (my $ip = $_[0]) =~ s!\.!\\\.!g;  register if $remote =~ /$ip$/  }}
		{ sub ip_dot    { (my $ip = $_[0]) =~ s!\.!\\\.!g;  register if $remote =~ /^$ip/  }}
		{ sub ALL       { register                                                         }}
		{ sub LOCAL     { register    if $remote !~ /\./                                   }}
		{ sub maskit    { my $r = new NetAddr::IP $remote  or return;
                                                    register   if (NetAddr::IP->new(shift)||return)  ->contains($r)  }}

      

                Start :     { init $arg[0], $arg[1] ; 'true'}
                                        Line(s)   /\Z/
                                        {$return = $found}
                Start:      {$return = $found}

                Line:       { $OK_remote = $OK_service = undef }
                Line:       { $side   = 'service', $e=0  }      List['']       ':'
                                        { $side   = 'remote' , $e=0  }      List['']       EOL(?)
                                        { found  and  $found  = 1    }
		    		    <reject: $found>
                Line:       Comment
                Line:       <resync>


                List   :    <leftop: Member[$arg[0]](s)   'EXCEPT'   List[ $e^=1 ] >
                List   :    Member[ $arg[0] ](s)

                Member :    Wildcard[ $arg[0] ]
                Member :    Pattern[  $arg[0] ]
                Member :    Netmask[  $arg[0] ]
		Member :    ...!/EXCEPT/i   /[A-Za-z]\w*/    
		    		    { tally $item[2], $arg[0]  ; 'true' }


                Wildcard:   / \b  (ALL | LOCAL)  \b /x
                                        { &{"$item[1]"}( $arg[0] ) ; 'true'}
                Pattern:    ...!/\w/    m!\.\S+!  
                                        { dot_host   $item[-1] ; 'true'}


                Pattern:    m!\S+\.!     ...!/[\w]/
                                        { ip_dot   $item[1] ; 'true'}

                Netmask:    {} <rulevar: $octet  = qr/\d{1,3}/ >
                                              <rulevar: $o3     = qr/(?:\.$octet){1,3}/ >
                Netmask:    m! \b  $octet $o3   (?: /$octet(?:$o3)? )? \b  !xo
                                        { maskit $item[1] , $arg[0]   ;  'true'}


		EOL    :    /[\n]/
		Comment:    /#.*\n/   
);



sub  TcpdParser : ATTR  { ${$_[2]} = new Parse::RecDescent( $grammar )  or die }

1;
__END__