Preserve shell variables when converting masq -> snat

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2016-11-06 13:53:05 -08:00
parent 6398756647
commit 1b82dedb77
No known key found for this signature in database
GPG Key ID: 96E6B3F2423A4D10
2 changed files with 190 additions and 71 deletions

View File

@ -175,6 +175,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
$doing $doing
$done $done
$currentline $currentline
$rawcurrentline
$currentfilename $currentfilename
$debug $debug
$file_format $file_format

View File

@ -60,12 +60,12 @@ sub initialize($) {
# #
# Process a single rule from the the masq file # Process a single rule from the the masq file
# #
sub process_one_masq1( $$$$$$$$$$$$ ) sub process_one_masq1( $$$$$$$$$$$ )
{ {
my ( $snat, $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) = @_; my ( $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) = @_;
my $pre_nat; my $pre_nat;
my $add_snat_aliases = ! $snat && $family == F_IPV4 && $config{ADD_SNAT_ALIASES}; my $add_snat_aliases = $family == F_IPV4 && $config{ADD_SNAT_ALIASES};
my $destnets = ''; my $destnets = '';
my $baserule = ''; my $baserule = '';
my $inlinematches = ''; my $inlinematches = '';
@ -226,7 +226,7 @@ sub process_one_masq1( $$$$$$$$$$$$ )
} elsif ( $addresses eq 'NONAT' ) { } elsif ( $addresses eq 'NONAT' ) {
fatal_error "'persistent' may not be specified with 'NONAT'" if $persistent; fatal_error "'persistent' may not be specified with 'NONAT'" if $persistent;
fatal_error "'random' may not be specified with 'NONAT'" if $randomize; fatal_error "'random' may not be specified with 'NONAT'" if $randomize;
$target = $snat ? 'CONTINUE' : 'RETURN'; $target = 'RETURN';
$add_snat_aliases = 0; $add_snat_aliases = 0;
} elsif ( $addresses ) { } elsif ( $addresses ) {
my $addrlist = ''; my $addrlist = '';
@ -249,7 +249,6 @@ sub process_one_masq1( $$$$$$$$$$$$ )
# #
$target = 'SNAT '; $target = 'SNAT ';
unless ( $snat ) {
if ( $interface =~ /^{([a-zA-Z_]\w*)}$/ ) { if ( $interface =~ /^{([a-zA-Z_]\w*)}$/ ) {
# #
# User-defined address variable # User-defined address variable
@ -276,7 +275,6 @@ sub process_one_masq1( $$$$$$$$$$$$ )
$addrlist .= '--to-source ' . $addr; $addrlist .= '--to-source ' . $addr;
} }
}
} elsif ( $family == F_IPV4 ) { } elsif ( $family == F_IPV4 ) {
if ( $addr =~ /^.*\..*\..*\./ ) { if ( $addr =~ /^.*\..*\..*\./ ) {
$target = 'SNAT '; $target = 'SNAT ';
@ -362,7 +360,6 @@ sub process_one_masq1( $$$$$$$$$$$$ )
# #
# And Generate the Rule(s) # And Generate the Rule(s)
# #
unless ( $snat ) {
expand_rule( $chainref , expand_rule( $chainref ,
POSTROUTE_RESTRICT , POSTROUTE_RESTRICT ,
$prerule , $prerule ,
@ -400,10 +397,88 @@ sub process_one_masq1( $$$$$$$$$$$$ )
} }
} }
} }
progress_message " Masq record \"$currentline\" $done";
}
sub convert_one_masq1( $$$$$$$$$$$$ )
{
my ( $snat, $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) = @_;
my $pre_nat;
my $destnets = '';
my $savelist;
#
# Leading '+'
#
$pre_nat = ( $interfacelist =~ s/^\+// );
#
# Check for INLINE
#
if ( $interfacelist =~ /^INLINE\((.+)\)$/ ) {
$interfacelist = $1;
}
$savelist = $interfacelist;
#
# Parse the remaining part of the INTERFACE column
#
if ( $family == F_IPV4 ) {
if ( $interfacelist =~ /^([^:]+)::([^:]*)$/ ) {
$destnets = $2;
$interfacelist = $1;
} elsif ( $interfacelist =~ /^([^:]+:[^:]+):([^:]+)$/ ) {
$destnets = $2;
$interfacelist = $1;
} elsif ( $interfacelist =~ /^([^:]+):$/ ) {
$interfacelist = $1;
} elsif ( $interfacelist =~ /^([^:]+):([^:]*)$/ ) {
my ( $one, $two ) = ( $1, $2 );
if ( $2 =~ /\./ || $2 =~ /^%/ ) {
$interfacelist = $one;
$destnets = $two;
}
}
} elsif ( $interfacelist =~ /^(.+?):(.+)$/ ) {
$interfacelist = $1;
$destnets = $2;
}
#
# If there is no source or destination then allow all addresses
#
$networks = ALLIP if $networks eq '-';
$destnets = ALLIP if $destnets eq '-';
my $target;
#
# Parse the ADDRESSES column
#
if ( $addresses ne '-' ) {
my $saveaddresses = $addresses;
if ( $addresses ne 'random' ) {
$addresses =~ s/:persistent$//;
$addresses =~ s/:random$//;
if ( $addresses eq 'detect' ) {
$target = 'SNAT';
} elsif ( $addresses eq 'NONAT' ) {
$target = 'CONTINUE';
} elsif ( $addresses ) {
if ( $addresses =~ /^:/ ) {
$target = 'MASQUERADE';
} else {
$target = 'SNAT';
}
}
}
$addresses = $saveaddresses;
} else {
$target = 'MASQUERADE';
} }
if ( $snat ) { if ( $snat ) {
$target =~ s/ .*//;
$target .= '+' if $pre_nat; $target .= '+' if $pre_nat;
if ( $addresses ne '-' && $addresses ne 'NONAT' ) { if ( $addresses ne '-' && $addresses ne 'NONAT' ) {
@ -424,7 +499,7 @@ sub process_one_masq1( $$$$$$$$$$$$ )
print $snat "$line\n"; print $snat "$line\n";
} }
progress_message " Masq record \"$currentline\" $done"; progress_message " Masq record \"$rawcurrentline\" Converted";
} }
@ -432,6 +507,25 @@ sub process_one_masq( $ )
{ {
my ( $snat ) = @_; my ( $snat ) = @_;
if ( $snat ) {
unless ( $rawcurrentline =~ /^\s*(?:#.*)?$/ ) {
#
# Line was not blank or all comment
#
my ($interfacelist, $networks, $addresses, $protos, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) =
split_rawline2( 'masq file',
{ interface => 0, source => 1, address => 2, proto => 3, port => 4, ipsec => 5, mark => 6, user => 7, switch => 8, origdest => 9, probability => 10 },
{}, #Nopad
undef, #Columns
1 ); #Allow inline matches
if ( $interfacelist ne '-' ) {
for my $proto ( split_list $protos, 'Protocol' ) {
convert_one_masq1( $snat, $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability );
}
}
}
} else {
my ($interfacelist, $networks, $addresses, $protos, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) = my ($interfacelist, $networks, $addresses, $protos, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ) =
split_line2( 'masq file', split_line2( 'masq file',
{ interface => 0, source => 1, address => 2, proto => 3, port => 4, ipsec => 5, mark => 6, user => 7, switch => 8, origdest => 9, probability => 10 }, { interface => 0, source => 1, address => 2, proto => 3, port => 4, ipsec => 5, mark => 6, user => 7, switch => 8, origdest => 9, probability => 10 },
@ -442,7 +536,8 @@ sub process_one_masq( $ )
fatal_error 'INTERFACE must be specified' if $interfacelist eq '-'; fatal_error 'INTERFACE must be specified' if $interfacelist eq '-';
for my $proto ( split_list $protos, 'Protocol' ) { for my $proto ( split_list $protos, 'Protocol' ) {
process_one_masq1( $snat, $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability ); process_one_masq1( $interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user, $condition, $origdest, $probability );
}
} }
} }
@ -497,7 +592,19 @@ sub convert_masq() {
my $have_masq_rules; my $have_masq_rules;
directive_callback( sub () { print $snat "$_[1]\n"; 0; } ); directive_callback(
sub ()
{
if ( $_[0] eq 'OMITTED' ) {
#
# Convert the raw rule
#
process_one_masq( $snat) if $snat;
} else {
print $snat "$_[1]\n"; 0;
}
}
);
first_entry( first_entry(
sub { sub {
@ -510,7 +617,18 @@ sub convert_masq() {
} }
); );
process_one_masq($snat), $have_masq_rules++ while read_a_line( NORMAL_READ ); while ( read_a_line( NORMAL_READ ) ) {
#
# Process the file normally
#
process_one_masq(0);
#
# Now Convert it
#
process_one_masq($snat);
$have_masq_rules++;
}
if ( $have_masq_rules ) { if ( $have_masq_rules ) {
progress_message2 "Converted $fn to $fn1"; progress_message2 "Converted $fn to $fn1";