diff --git a/Shorewall-perl/Shorewall/Accounting.pm b/Shorewall-perl/Shorewall/Accounting.pm index 5cad573ec..fdc237cd1 100644 --- a/Shorewall-perl/Shorewall/Accounting.pm +++ b/Shorewall-perl/Shorewall/Accounting.pm @@ -198,29 +198,16 @@ sub setup_accounting() { if ( $filter_table->{accounting} ) { for my $chain ( qw/INPUT FORWARD/ ) { insert_rule $filter_table->{$chain}, 1, '-j accounting'; - insert_rule $filter_table->{$chain}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT}; - } - } elsif ( $config{FASTACCEPT} ) { - for my $chain ( qw/INPUT FORWARD/ ) { - insert_rule $filter_table->{$chain}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT'; } } if ( $filter_table->{accountout} ) { insert_rule $filter_table->{OUTPUT}, 1, '-j accountout'; - insert_rule $filter_table->{OUTPUT}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT}; - } elsif ( $config{FASTACCEPT} ) { - insert_rule $filter_table->{OUTPUT}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT'; } } else { if ( $filter_table->{accounting} ) { for my $chain ( qw/INPUT FORWARD OUTPUT/ ) { insert_rule $filter_table->{$chain}, 1, '-j accounting'; - insert_rule $filter_table->{$chain}, 2, '-m state --state ESTABLISHED,RELATED -j ACCEPT' if $config{FASTACCEPT}; - } - } elsif ( $config{FASTACCEPT} ) { - for my $chain ( qw/INPUT FORWARD OUTPUT/ ) { - insert_rule $filter_table->{$chain}, 1, '-m state --state ESTABLISHED,RELATED -j ACCEPT'; } } } diff --git a/Shorewall-perl/Shorewall/Actions.pm b/Shorewall-perl/Shorewall/Actions.pm index ce898ae0d..b6facdfe5 100644 --- a/Shorewall-perl/Shorewall/Actions.pm +++ b/Shorewall-perl/Shorewall/Actions.pm @@ -54,7 +54,7 @@ our @EXPORT = qw( merge_levels %macros ); our @EXPORT_OK = qw( initialize ); -our $VERSION = 4.01; +our $VERSION = 4.03; # # Used Actions. Each action that is actually used has an entry with value 1. @@ -389,12 +389,14 @@ sub process_macro1 ( $$ ) { $mtarget =~ s/:.*$//; + $mtarget = (split '/' , $mtarget)[0]; + my $targettype = $targets{$mtarget}; $targettype = 0 unless defined $targettype; fatal_error "Invalid target ($mtarget)" - unless ( $targettype == STANDARD ) || ( $mtarget eq 'PARAM' ) || ( $mtarget eq 'LOG' ); + unless ( $targettype == STANDARD ) || ( $mtarget eq 'PARAM' ) || ( $targettype & ( LOGRULE | NFQ ) ); } progress_message " ..End Macro $macrofile"; @@ -412,7 +414,7 @@ sub process_action1 ( $$ ) { my $targettype = $targets{$target}; if ( defined $targettype ) { - return if ( $targettype == STANDARD ) || ( $targettype == MACRO ) || ( $targettype & LOGRULE ); + return if ( $targettype == STANDARD ) || ( $targettype == MACRO ) || ( $targettype & ( LOGRULE | NFQ ) ); fatal_error "Invalid TARGET ($target)" if $targettype & STANDARD; @@ -424,6 +426,8 @@ sub process_action1 ( $$ ) { } else { ( $target, my $param ) = split '/', $target; + return if $target eq 'NFQUEUE'; + if ( defined $param ) { my $paramtype = $targets{$param} || 0; @@ -462,8 +466,8 @@ sub process_actions1() { next unless $action; if ( $targets{$action} ) { - next if $targets{$action} & ACTION; - fatal_error "Invalid Action Name ($action)"; + warning_message "Duplicate Action Name ($action) Ignored" unless $targets{$action} & ACTION; + next; } $targets{$action} = ACTION; @@ -632,7 +636,7 @@ sub process_action3( $$$$$ ) { if ( $action2type & ACTION ) { $target2 = (find_logactionchain ( $target = $target2 ))->{name}; } else { - die "Internal Error" unless $action2type == MACRO || $action2type & LOGRULE; + fatal_error "Internal Error" unless $action2type == MACRO || $action2type & ( LOGRULE | NFQ ); } } @@ -666,10 +670,10 @@ sub process_actions3 () { add_rule $chainref, '-m addrtype --dst-type BROADCAST -j DROP'; } else { add_command $chainref, 'for address in $ALL_BCASTS; do'; - push_cmd_mode $chainref; + incr_cmd_level $chainref; log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -d $address ' if $level ne ''; add_rule $chainref, '-d $address -j DROP'; - pop_cmd_mode $chainref; + decr_cmd_level $chainref; add_command $chainref, 'done'; log_rule_limit $level, $chainref, 'dropBcast' , 'DROP', '', $tag, 'add', ' -d 224.0.0.0/4 ' if $level ne ''; @@ -690,10 +694,10 @@ sub process_actions3 () { add_rule $chainref, '-m addrtype --dst-type BROADCAST -j ACCEPT'; } else { add_command $chainref, 'for address in $ALL_BCASTS; do'; - push_cmd_mode $chainref; + incr_cmd_level $chainref; log_rule_limit $level, $chainref, 'allowBcast' , 'ACCEPT', '', $tag, 'add', ' -d $address ' if $level ne ''; add_rule $chainref, '-d $address -j ACCEPT'; - pop_cmd_mode $chainref; + decr_cmd_level $chainref; add_command $chainref, 'done'; log_rule_limit $level, $chainref, 'allowBcast' , 'ACCEPT', '', $tag, 'add', ' -d 224.0.0.0/4 ' if $level ne ''; diff --git a/Shorewall-perl/Shorewall/Chains.pm b/Shorewall-perl/Shorewall/Chains.pm index 2f571ad94..bd6ad2bc1 100644 --- a/Shorewall-perl/Shorewall/Chains.pm +++ b/Shorewall-perl/Shorewall/Chains.pm @@ -44,6 +44,7 @@ our @EXPORT = qw( STANDARD ACTION MACRO LOGRULE + NFQ NO_RESTRICT PREROUTE_RESTRICT INPUT_RESTRICT @@ -52,14 +53,15 @@ our @EXPORT = qw( STANDARD ALL_RESTRICT process_comment - push_cmd_mode - pop_cmd_mode + incr_cmd_level + decr_cmd_level add_command add_commands mark_referenced add_file add_rule insert_rule + insert_rule_nice chain_base forward_chain input_chain @@ -89,7 +91,6 @@ our @EXPORT = qw( STANDARD clearrule do_proto mac_match - numeric_value verify_mark verify_small_mark validate_mark @@ -128,7 +129,7 @@ our @EXPORT = qw( STANDARD %targets ); our @EXPORT_OK = qw( initialize ); -our $VERSION = 4.02; +our $VERSION = 4.03; # # Chain Table @@ -138,16 +139,17 @@ our $VERSION = 4.02; # %chain_table { => { => { name => # table =>
# is_policy => 0|1 -# is_optionsl => 0|1 +# is_optional => 0|1 # referenced => 0|1 # log => # policy => +# policychain => -- self-reference if this is a policy chain +# policypair => [ , ] -- Used for reporting duplicated policies # loglevel => # synparams => # synchain => # default => -# policy_chain => -# cmdmode => +# cmdlevel => # rules => [ # # ... @@ -188,6 +190,7 @@ use constant { STANDARD => 1, #defined by Netfilter ACTION => 64, #An action (may be built-in) MACRO => 128, #A Macro LOGRULE => 256, #'LOG' + NFQ => 512, #'NFQUEUE' }; our %targets; @@ -276,6 +279,8 @@ sub initialize() { 'CONTINUE!' => STANDARD, 'QUEUE' => STANDARD, 'QUEUE!' => STANDARD, + 'NFQUEUE' => STANDARD + NFQ, + 'NFQUEUE!' => STANDARD + NFQ, 'SAME' => NATRULE, 'SAME-' => NATRULE + NATONLY, 'dropBcast' => BUILTIN + ACTION, @@ -331,21 +336,21 @@ sub process_comment() { } } # -# Functions to manipulate cmdmode +# Functions to manipulate cmdlevel # -sub push_cmd_mode( $ ) { - $_[0]->{cmdmode}++; +sub incr_cmd_level( $ ) { + $_[0]->{cmdlevel}++; } -sub pop_cmd_mode( $ ) { - fatal_error "Internal error in pop_cmd_mode()" if --$_[0]->{cmdmode} < 0; +sub decr_cmd_level( $ ) { + fatal_error "Internal error in decr_cmd_level()" if --$_[0]->{cmdlevel} < 0; } sub add_command($$) { my ($chainref, $command) = @_; - push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdmode} , $command ); + push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdlevel} , $command ); $chainref->{referenced} = 1; } @@ -354,7 +359,7 @@ sub add_commands { my $chainref = shift @_; for my $command ( @_ ) { - push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdmode} , $command ); + push @{$chainref->{rules}}, join ('', ' ' x $chainref->{cmdlevel} , $command ); } $chainref->{referenced} = 1; @@ -403,7 +408,7 @@ sub add_rule($$) $rule .= qq( -m comment --comment "$comment") if $comment; - if ( $chainref->{cmdmode} ) { + if ( $chainref->{cmdlevel} ) { $rule =~ s/"/\\"/g; #Must preserve quotes in the rule add_command $chainref , qq(echo "-A $chainref->{name} $rule" >&3); } else { @@ -421,7 +426,7 @@ sub insert_rule($$$) { my ($chainref, $number, $rule) = @_; - fatal_error 'Internal Error in insert_rule()' if $chainref->{cmdmode}; + fatal_error 'Internal Error in insert_rule()' if $chainref->{cmdlevel}; $rule .= "-m comment --comment \"$comment\"" if $comment; @@ -445,12 +450,16 @@ sub chain_base($) { $chain; } +sub chain_base_cond($) { + $config{DYNAMIC_ZONES} ? chain_base($_[0]) : $_[0]; +} + # # Forward Chain for an interface # sub forward_chain($) { - $_[0] . '_fwd'; + chain_base_cond($_[0]) . '_fwd'; } # @@ -458,7 +467,7 @@ sub forward_chain($) # sub input_chain($) { - $_[0] . '_in'; + chain_base_cond($_[0]) . '_in'; } # @@ -466,7 +475,7 @@ sub input_chain($) # sub output_chain($) { - $_[0] . '_out'; + chain_base_cond($_[0]) . '_out'; } # @@ -474,7 +483,7 @@ sub output_chain($) # sub masq_chain($) { - $_[0] . '_masq'; + chain_base_cond($_[0]) . '_masq'; } # @@ -489,12 +498,12 @@ sub syn_flood_chain ( $ ) { # sub mac_chain( $ ) { - $_[0] . '_mac'; + chain_base_cond($_[0]) . '_mac'; } sub macrecent_target($) { - $config{MACLIST_TTL} ? $_[0] . '_rec' : 'RETURN'; + $config{MACLIST_TTL} ? chain_base_cond($_[0]) . '_rec' : 'RETURN'; } # @@ -502,22 +511,22 @@ sub macrecent_target($) # sub dynamic_fwd( $ ) { - $_[0] . '_dynf'; + chain_base_cond($_[0]) . '_dynf'; } sub dynamic_in( $ ) { - $_[0] . '_dyni'; + chain_base_cond($_[0]) . '_dyni'; } sub dynamic_out( $ ) # $1 = interface { - $_[0] . '_dyno'; + chain_base_cond($_[0]) . '_dyno'; } sub dynamic_chains( $ ) #$1 = interface { - my $c = $_[0]; + my $c = chain_base_cond($_[0]); [ $c . '_dyni' , $c . '_dynf' , $c . '_dyno' ]; } @@ -527,7 +536,7 @@ sub dynamic_chains( $ ) #$1 = interface # sub dnat_chain( $ ) { - $_[0] . '_dnat'; + chain_base_cond($_[0]) . '_dnat'; } # @@ -535,7 +544,7 @@ sub dnat_chain( $ ) # sub snat_chain( $ ) { - $_[0] . '_snat'; + chain_base_cond($_[0]) . '_snat'; } # @@ -543,7 +552,7 @@ sub snat_chain( $ ) # sub ecn_chain( $ ) { - $_[0] . '_ecn'; + chain_base_cond($_[0]) . '_ecn'; } # @@ -551,7 +560,7 @@ sub ecn_chain( $ ) # sub first_chains( $ ) #$1 = interface { - my $c = $_[0]; + my $c = chain_base_cond($_[0]); [ $c . '_fwd', $c . '_in' ]; } @@ -563,12 +572,14 @@ sub new_chain($$) { my ($table, $chain) = @_; + warning_message "Internal error in new_chain()" if $chain_table{$table}{$chain}; + $chain_table{$table}{$chain} = { name => $chain, rules => [], table => $table, loglevel => '', log => 1, - cmdmode => 0 }; + cmdlevel => 0 }; } # @@ -668,7 +679,7 @@ sub initialize_chain_table() new_builtin_chain 'nat', $chain, 'ACCEPT'; } - for my $chain qw(PREROUTING INPUT FORWARD OUTPUT POSTROUTING) { + for my $chain qw(PREROUTING INPUT OUTPUT ) { new_builtin_chain 'mangle', $chain, 'ACCEPT'; } @@ -693,7 +704,7 @@ sub finish_chain_section ($$) { if ( $chainref->{synparams} ) { my $synchainref = ensure_chain 'filter', syn_flood_chain $chainref; if ( $section eq 'DONE' ) { - if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE)$/ ) { + if ( $chainref->{policy} =~ /^(ACCEPT|CONTINUE|QUEUE|NFQUEUE)/ ) { add_rule $chainref, "-p tcp --syn -j $synchainref->{name}"; } } else { @@ -762,7 +773,7 @@ sub set_mss( $$$ ) { } # -# Interate over non-firewall zones adding TCPMSS rules as appropriate +# Interate over non-firewall zones and interfaces with 'mss=' setting adding TCPMSS rules as appropriate. # sub setup_zone_mss() { for my $zone ( @zones ) { @@ -984,15 +995,6 @@ sub mac_match( $ ) { "--match mac --mac-source ${invert}$mac "; } -# -# Convert value to decimal number -# -sub numeric_value ( $ ) { - my $mark = $_[0]; - fatal_error "Invalid Numeric Value ($mark)" unless "\L$mark" =~ /^(0x[a-f0-9]+|0[0-7]*|[1-9]\d*)$/; - $mark =~ /^0x/ ? hex $mark : $mark =~ /^0/ ? oct $mark : $mark; -} - # # Mark validatation functions # @@ -1224,8 +1226,10 @@ sub match_orig_dest ( $ ) { if ( $net =~ /^!/ ) { $net =~ s/!//; + validate_net $net; "-m conntrack --ctorigdst ! $net "; } else { + validate_net $net; $net eq ALLIPv4 ? '' : "-m conntrack --ctorigdst $net "; } } @@ -1301,7 +1305,7 @@ sub log_rule_limit( $$$$$$$$ ) { } if ( length $prefix > 29 ) { - $prefix = substr $prefix, 0, 29; + $prefix = substr( $prefix, 0, 28 ) . ' '; warning_message "Log Prefix shortened to \"$prefix\""; } @@ -1473,7 +1477,7 @@ sub expand_rule( $$$$$$$$$$ ) my ($iiface, $diface, $inets, $dnets, $iexcl, $dexcl, $onets , $oexcl ); my $chain = $chainref->{name}; - my $initialcmdmode = $chainref->{cmdmode}; + my $initialcmdlevel = $chainref->{cmdlevel}; # # Handle Log Level @@ -1531,7 +1535,7 @@ sub expand_rule( $$$$$$$$$$ ) $rule .= '-s $source '; - push_cmd_mode $chainref; + incr_cmd_level $chainref; } else { fatal_error "Source Interface ($iiface) not allowed when the source zone is $firewall_zone" if $restriction & OUTPUT_RESTRICT; $rule .= match_source_dev( $iiface ); @@ -1560,7 +1564,7 @@ sub expand_rule( $$$$$$$$$$ ) add_command( $chainref , "for address in $list; do" ); $rule .= '-d $address '; - push_cmd_mode $chainref; + incr_cmd_level $chainref; } else { $rule .= join ( '', '-d ', get_interface_address( $interfaces[0] ), ' ' ); } @@ -1591,7 +1595,7 @@ sub expand_rule( $$$$$$$$$$ ) fatal_error "Bridge port ($diface) not allowed" if port_to_bridge( $diface ); add_command( $chainref , 'for dest in ' . get_interface_addresses( $diface) . '; do' ); $rule .= '-d $dest '; - push_cmd_mode $chainref; + incr_cmd_level $chainref; } else { fatal_error "Bridge Port ($diface) not allowed in OUTPUT or POSTROUTING rules" if ( $restriction & ( POSTROUTE_RESTRICT + OUTPUT_RESTRICT ) ) && port_to_bridge( $diface ); fatal_error "Destination Interface ($diface) not allowed when the destination zone is $firewall_zone" if $restriction & INPUT_RESTRICT; @@ -1625,7 +1629,7 @@ sub expand_rule( $$$$$$$$$$ ) add_command( $chainref , "for address in $list; do" ); $rule .= '-m conntrack --ctorigdst $address '; - push_cmd_mode $chainref; + incr_cmd_level $chainref; } else { get_interface_address $interfaces[0]; $rule .= join( '', '-m conntrack --ctorigdst $', interface_address ( $interfaces[0] ), ' ' ); @@ -1649,7 +1653,7 @@ sub expand_rule( $$$$$$$$$$ ) unless ( $onets ) { my @oexcl = mysplit $oexcl; if ( @oexcl == 1 ) { - $rule .= "-m conntrack --ctorigdst ! $oexcl "; + $rule .= match_orig_dest( "!$oexcl" ); $oexcl = ''; } } @@ -1727,19 +1731,13 @@ sub expand_rule( $$$$$$$$$$ ) for my $inet ( mysplit $inets ) { for my $dnet ( mysplit $dnets ) { # - # We defer evaluating the source net match to accomodate system without $capabilities{KLUDGEFREE} + # We evaluate the source net match in the inner loop to accomodate systems without $capabilities{KLUDGEFREE} # add_rule $chainref, join( '', $rule, match_source_net( $inet), match_dest_net( $dnet ), $onet, "-j $echain" ); } } } - # - # The final rule in the exclusion chain will not qualify the source or destination - # - $inets = ALLIPv4; - $dnets = ALLIPv4; - # # Create the Exclusion Chain # @@ -1748,17 +1746,9 @@ sub expand_rule( $$$$$$$$$$ ) # # Generate RETURNs for each exclusion # - for my $net ( mysplit $iexcl ) { - add_rule $echainref, ( match_source_net $net ) . '-j RETURN'; - } - - for my $net ( mysplit $dexcl ) { - add_rule $echainref, ( match_dest_net $net ) . '-j RETURN'; - } - - for my $net ( mysplit $oexcl ) { - add_rule $echainref, ( match_orig_dest $net ) . '-j RETURN'; - } + add_rule $echainref, ( match_source_net $_ ) . '-j RETURN' for ( mysplit $iexcl ); + add_rule $echainref, ( match_dest_net $_ ) . '-j RETURN' for ( mysplit $dexcl ); + add_rule $echainref, ( match_orig_dest $_ ) . '-j RETURN' for ( mysplit $oexcl ); # # Log rule # @@ -1800,8 +1790,8 @@ sub expand_rule( $$$$$$$$$$ ) } } - while ( $chainref->{cmdmode} > $initialcmdmode ) { - pop_cmd_mode $chainref; + while ( $chainref->{cmdlevel} > $initialcmdlevel ) { + decr_cmd_level $chainref; add_command $chainref, 'done'; } @@ -1974,7 +1964,7 @@ sub create_netfilter_load() { for my $chain ( @builtins ) { my $chainref = $chain_table{$table}{$chain}; if ( $chainref ) { - fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdmode}; + fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdlevel}; emit_unindented ":$chain $chainref->{policy} [0:0]"; push @chains, $chainref; } @@ -1985,7 +1975,7 @@ sub create_netfilter_load() { for my $chain ( grep $chain_table{$table}{$_}->{referenced} , ( sort keys %{$chain_table{$table}} ) ) { my $chainref = $chain_table{$table}{$chain}; unless ( $chainref->{builtin} ) { - fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdmode}; + fatal_error "Internal error in create_netfilter_load()" if $chainref->{cmdlevel}; emit_unindented ":$chainref->{name} - [0:0]"; push @chains, $chainref; } diff --git a/Shorewall-perl/Shorewall/Compiler.pm b/Shorewall-perl/Shorewall/Compiler.pm index a16a8e76b..3d0a15d09 100644 --- a/Shorewall-perl/Shorewall/Compiler.pm +++ b/Shorewall-perl/Shorewall/Compiler.pm @@ -41,7 +41,7 @@ use Shorewall::Proxyarp; our @ISA = qw(Exporter); our @EXPORT = qw( compiler EXPORT TIMESTAMP DEBUG ); our @EXPORT_OK = qw( $export ); -our $VERSION = 4.02; +our $VERSION = 4.03; our $export; @@ -85,7 +85,7 @@ sub generate_script_1() { copy $globals{SHAREDIRPL} . 'prog.header'; - for my $exit qw/init start tcclear started stop stopped clear refresh refreshed/ { + for my $exit qw/init isusable start tcclear started stop stopped clear refresh refreshed/ { emit "\nrun_${exit}_exit() {"; push_indent; append_file $exit or emit 'true'; @@ -581,8 +581,6 @@ sub generate_script_2 () { push_indent; - setup_mss( $config{CLAMPMSS} ) if $config{CLAMPMSS}; - } # @@ -775,6 +773,10 @@ sub compiler( $$$$ ) { # generate_script_2 unless $command eq 'check'; # + # Set up MSS rules + # + setup_mss; + # # Do all of the zone-independent stuff # add_common_rules; diff --git a/Shorewall-perl/Shorewall/Config.pm b/Shorewall-perl/Shorewall/Config.pm index 34baac915..85a49b3da 100644 --- a/Shorewall-perl/Shorewall/Config.pm +++ b/Shorewall-perl/Shorewall/Config.pm @@ -93,7 +93,7 @@ our @EXPORT = qw( %capabilities ); our @EXPORT_OK = qw( $shorewall_dir initialize read_a_line1 set_config_path ); -our $VERSION = 4.02; +our $VERSION = 4.03; # # describe the current command, it's present progressive, and it's completion. @@ -198,8 +198,8 @@ sub initialize() { ORIGINAL_POLICY_MATCH => '', LOGPARMS => '', TC_SCRIPT => '', - VERSION => '4.0.2', - CAPVERSION => 30405 , + VERSION => '4.0.3', + CAPVERSION => 40003 , ); # # From shorewall.conf file @@ -247,6 +247,7 @@ sub initialize() { REJECT_DEFAULT => undef, ACCEPT_DEFAULT => undef, QUEUE_DEFAULT => undef, + NFQUEUE_DEFAULT => undef, # # RSH/RCP Commands # @@ -328,6 +329,9 @@ sub initialize() { MANGLE_FORWARD => undef, COMMENTS => undef, ADDRTYPE => undef, + TCPMSS_MATCH => undef, + HASHLIMIT_MATCH => undef, + NFQUEUE_TARGET => undef, CAPVERSION => undef, ); # @@ -360,7 +364,9 @@ sub initialize() { MANGLE_FORWARD => 'Mangle FORWARD Chain', COMMENTS => 'Comments', ADDRTYPE => 'Address Type Match', - TCPMSS_MATCH => 'TCP MSS', + TCPMSS_MATCH => 'TCPMSS Match', + HASHLIMIT_MATCH => 'Hashlimit Match', + NFQUEUE_TARGET => 'NFQUEUE Target', CAPVERSION => 'Capability Version', ); # @@ -1180,9 +1186,11 @@ sub determine_capabilities() { } } - $capabilities{USEPKTTYPE} = qt( "$iptables -A $sillyname -m pkttype --pkt-type broadcast -j ACCEPT" ); - $capabilities{ADDRTYPE} = qt( "$iptables -A $sillyname -m addrtype --src-type BROADCAST -j ACCEPT" ); - $capabilities{TCPMSS_MATCH} = qt( "$iptables -A $sillyname -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT" ); + $capabilities{USEPKTTYPE} = qt( "$iptables -A $sillyname -m pkttype --pkt-type broadcast -j ACCEPT" ); + $capabilities{ADDRTYPE} = qt( "$iptables -A $sillyname -m addrtype --src-type BROADCAST -j ACCEPT" ); + $capabilities{TCPMSS_MATCH} = qt( "$iptables -A $sillyname -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT" ); + $capabilities{HASHLIMIT_MATCH} = qt( "$iptables -A $sillyname -m hashlimit --hashlimit 4 --hashlimit-burst 5 --hashlimit-name fooX1234 --hashlimit-mode dstip -j ACCEPT" ); + $capabilities{NFQUEUE_TARGET} = qt( "$iptables -A $sillyname -j NFQUEUE --queue-num 4" ); qt( "$iptables -F $sillyname" ); qt( "$iptables -X $sillyname" ); @@ -1418,7 +1426,7 @@ sub get_configuration( $ ) { default_yes_no 'EXPORTPARAMS' , ''; default_yes_no 'EXPAND_POLICIES' , ''; - default_yes_no 'ACCOUNTING_EXPERT' , ''; + default_yes_no 'KEEP_RT_TABLES' , ''; default_yes_no 'MARK_IN_FORWARD_CHAIN' , ''; $capabilities{XCONNMARK} = '' unless $capabilities{XCONNMARK_MATCH} and $capabilities{XMARK}; @@ -1480,16 +1488,17 @@ sub get_configuration( $ ) { } default 'RESTOREFILE' , 'restore'; + default 'IPSECFILE' , 'zones'; default 'DROP_DEFAULT' , 'Drop'; default 'REJECT_DEFAULT' , 'Reject'; default 'QUEUE_DEFAULT' , 'none'; + default 'NFQUEUE_DEFAULT' , 'none'; default 'ACCEPT_DEFAULT' , 'none'; default 'OPTIMIZE' , 0; - default 'IPSECFILE' , 'zones'; fatal_error 'IPSECFILE=ipsec is not supported by Shorewall-perl ' . $globals{VERSION} unless $config{IPSECFILE} eq 'zones'; - for my $default qw/DROP_DEFAULT REJECT_DEFAULT QUEUE_DEFAULT ACCEPT_DEFAULT/ { + for my $default qw/DROP_DEFAULT REJECT_DEFAULT QUEUE_DEFAULT NFQUEUE_DEFAULT ACCEPT_DEFAULT/ { $config{$default} = 'none' if "\L$config{$default}" eq 'none'; } diff --git a/Shorewall-perl/Shorewall/IPAddrs.pm b/Shorewall-perl/Shorewall/IPAddrs.pm index ebe9b3ecb..111f991f0 100644 --- a/Shorewall-perl/Shorewall/IPAddrs.pm +++ b/Shorewall-perl/Shorewall/IPAddrs.pm @@ -41,7 +41,7 @@ our @EXPORT = qw( ALLIPv4 @rfc1918_networks ); our @EXPORT_OK = qw( ); -our $VERSION = 4.00; +our $VERSION = 4.03; # # Some IPv4 useful stuff @@ -75,6 +75,8 @@ sub validate_address( $ ) { sub validate_net( $ ) { my ($net, $vlsm, $rest) = split( '/', $_[0], 3 ); + fatal_error "An ipset name ($net) is not allowed in this context" if substr( $net, 0, 1 ) eq '+'; + if ( defined $vlsm ) { fatal_error "Invalid VLSM ($vlsm)" unless $vlsm =~ /^\d+$/ && $vlsm <= 32; fatal_error "Invalid Network address ($_[0])" if defined $rest; diff --git a/Shorewall-perl/Shorewall/Nat.pm b/Shorewall-perl/Shorewall/Nat.pm index 4d71b0f92..e26a94ed5 100644 --- a/Shorewall-perl/Shorewall/Nat.pm +++ b/Shorewall-perl/Shorewall/Nat.pm @@ -36,7 +36,7 @@ use strict; our @ISA = qw(Exporter); our @EXPORT = qw( setup_masq setup_nat setup_netmap add_addresses ); our @EXPORT_OK = (); -our $VERSION = 4.00; +our $VERSION = 4.03; our @addresses_to_add; our %addresses_to_add; @@ -212,7 +212,7 @@ sub setup_one_masq($$$$$$$) add_commands( $chainref, '', "if [ \"$variable\" != 0.0.0.0 ]; then" ); - push_cmd_mode( $chainref ); + incr_cmd_level( $chainref ); $detectaddress = 1; } } else { @@ -249,7 +249,7 @@ sub setup_one_masq($$$$$$$) $exceptionrule ); if ( $detectaddress ) { - pop_cmd_mode( $chainref ); + decr_cmd_level( $chainref ); add_command( $chainref , 'fi' ); } diff --git a/Shorewall-perl/Shorewall/Policy.pm b/Shorewall-perl/Shorewall/Policy.pm index 6de28294c..e9751f145 100644 --- a/Shorewall-perl/Shorewall/Policy.pm +++ b/Shorewall-perl/Shorewall/Policy.pm @@ -34,21 +34,32 @@ use strict; our @ISA = qw(Exporter); our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain sub setup_syn_flood_chains ); our @EXPORT_OK = qw( ); -our $VERSION = 4.02; +our $VERSION = 4.03; # -# Create a new policy chain and return a reference to it. +# Convert a chain into a policy chain. # -sub new_policy_chain($$$) +sub convert_to_policy_chain($$$$$) { - my ($chain, $policy, $optional) = @_; - - my $chainref = new_chain 'filter', $chain; + my ($chainref, $source, $dest, $policy, $optional ) = @_; $chainref->{is_policy} = 1; $chainref->{policy} = $policy; $chainref->{is_optional} = $optional; - $chainref->{policychain} = $chain; + $chainref->{policychain} = $chainref->{name}; + $chainref->{policypair} = [ $source, $dest ]; +} + +# +# Create a new policy chain and return a reference to it. +# +sub new_policy_chain($$$$) +{ + my ($source, $dest, $policy, $optional) = @_; + + my $chainref = new_chain( 'filter', "${source}2${dest}" ); + + convert_to_policy_chain( $chainref, $source, $dest, $policy, $optional ); $chainref; } @@ -56,9 +67,9 @@ sub new_policy_chain($$$) # # Set the passed chain's policychain and policy to the passed values. # -sub set_policy_chain($$$) +sub set_policy_chain($$$$$) { - my ($chain1, $chainref, $policy) = @_; + my ($source, $dest, $chain1, $chainref, $policy ) = @_; my $chainref1 = $filter_table->{$chain1}; @@ -86,6 +97,7 @@ sub set_policy_chain($$$) } $chainref1->{policy} = $policy; + $chainref1->{policypair} = [ $source, $dest ]; } } @@ -97,8 +109,13 @@ sub validate_policy() sub print_policy($$$$) { my ( $source, $dest, $policy , $chain ) = @_; - progress_message " Policy for $source to $dest is $policy using chain $chain" - unless ( $source eq $dest ) || ( $source eq 'all' ) || ( $dest eq 'all' ); + unless ( ( $source eq 'all' ) || ( $dest eq 'all' ) ) { + if ( $policy eq 'CONTINUE' ) { + my ( $sourceref, $destref ) = @zones{$source,$dest}; + warning_message "CONTINUE policy between two un-nested zones ($source, $dest)" if ! ( @{$sourceref->{parents}} || @{$destref->{parents}} ); + } + progress_message " Policy for $source to $dest is $policy using chain $chain" unless $source eq $dest; + } } my %validpolicies = ( @@ -107,19 +124,21 @@ sub validate_policy() DROP => undef, CONTINUE => undef, QUEUE => undef, + NFQUEUE => undef, NONE => undef ); - my %map = ( DROP_DEFAULT => 'DROP' , - REJECT_DEFAULT => 'REJECT' , - ACCEPT_DEFAULT => 'ACCEPT' , - QUEUE_DEFAULT => 'QUEUE' ); + my %map = ( DROP_DEFAULT => 'DROP' , + REJECT_DEFAULT => 'REJECT' , + ACCEPT_DEFAULT => 'ACCEPT' , + QUEUE_DEFAULT => 'QUEUE' , + NFQUEUE_DEFAULT => 'NFQUEUE' ); my $zone; use constant { OPTIONAL => 1 }; - for my $option qw/DROP_DEFAULT REJECT_DEFAULT ACCEPT_DEFAULT QUEUE_DEFAULT/ { + for my $option qw/DROP_DEFAULT REJECT_DEFAULT ACCEPT_DEFAULT QUEUE_DEFAULT NFQUEUE_DEFAULT/ { my $action = $config{$option}; next if $action eq 'none'; my $actiontype = $targets{$action}; @@ -139,13 +158,13 @@ sub validate_policy() } for $zone ( @zones ) { - push @policy_chains, ( new_policy_chain "${zone}2${zone}", 'ACCEPT', OPTIONAL ); + push @policy_chains, ( new_policy_chain $zone, $zone, 'ACCEPT', OPTIONAL ); if ( $config{IMPLICIT_CONTINUE} && ( @{$zones{$zone}{parents}} ) ) { for my $zone1 ( @zones ) { next if $zone eq $zone1; - push @policy_chains, ( new_policy_chain "${zone}2${zone1}", 'CONTINUE', OPTIONAL ); - push @policy_chains, ( new_policy_chain "${zone1}2${zone}", 'CONTINUE', OPTIONAL ); + push @policy_chains, ( new_policy_chain $zone, $zone1, 'CONTINUE', OPTIONAL ); + push @policy_chains, ( new_policy_chain $zone1, $zone, 'CONTINUE', OPTIONAL ); } } } @@ -178,6 +197,8 @@ sub validate_policy() fatal_error "Invalid default action ($default:$remainder)" if defined $remainder; + ( $policy , my $queue ) = split( '/' , $policy ); + if ( $default ) { if ( "\L$default" eq 'none' ) { $default = 'none'; @@ -199,7 +220,13 @@ sub validate_policy() fatal_error "Invalid policy $policy" unless exists $validpolicies{$policy}; - if ( $policy eq 'NONE' ) { + if ( defined $queue ) { + fatal_error "Invalid policy ($policy/$queue)" unless $policy eq 'NFQUEUE'; + require_capability( 'NFQUEUE_TARGET', 'An NFQUEUE Policy', 's' ); + $queue = numeric_value( $queue ); + fatal_error "Invalid NFQUEUE queue number ($queue)" if $queue > 65535; + $policy = "$policy/$queue"; + } elsif ( $policy eq 'NONE' ) { fatal_error "NONE policy not allowed with \"all\"" if $clientwild || $serverwild; fatal_error "NONE policy not allowed to/from firewall zone" @@ -224,18 +251,16 @@ sub validate_policy() $chainref->{is_optional} = 0; $chainref->{policy} = $policy; } else { - fatal_error "Duplicate policy: $client $server $policy"; + fatal_error qq(Policy "$client $server $policy" duplicates earlier policy "@{$chainref->{policypair}} $chainref->{policy}"); } } elsif ( $chainref->{policy} ) { - fatal_error "Duplicate policy: $client $server $policy"; + fatal_error qq(Policy "$client $server $policy" duplicates earlier policy "@{$chainref->{policypair}} $chainref->{policy}"); } else { - $chainref->{is_policy} = 1; - $chainref->{policy} = $policy; - $chainref->{policychain} = $chain; + convert_to_policy_chain( $chainref, $client, $server, $policy, 0 ); push @policy_chains, ( $chainref ) unless $config{EXPAND_POLICIES} && ( $clientwild || $serverwild ); } } else { - $chainref = new_policy_chain $chain, $policy, 0; + $chainref = new_policy_chain $client, $server, $policy, 0; push @policy_chains, ( $chainref ) unless $config{EXPAND_POLICIES} && ( $clientwild || $serverwild ); } @@ -252,19 +277,19 @@ sub validate_policy() if ( $serverwild ) { for my $zone ( @zones , 'all' ) { for my $zone1 ( @zones , 'all' ) { - set_policy_chain "${zone}2${zone1}", $chainref, $policy; + set_policy_chain $client, $server, "${zone}2${zone1}", $chainref, $policy; print_policy $zone, $zone1, $policy, $chain; } } } else { for my $zone ( @zones ) { - set_policy_chain "${zone}2${server}", $chainref, $policy; + set_policy_chain $client, $server, "${zone}2${server}", $chainref, $policy; print_policy $zone, $server, $policy, $chain; } } } elsif ( $serverwild ) { for my $zone ( @zones , 'all' ) { - set_policy_chain "${client}2${zone}", $chainref, $policy; + set_policy_chain $client, $server, "${client}2${zone}", $chainref, $policy; print_policy $client, $zone, $policy, $chain; } @@ -284,7 +309,14 @@ sub policy_rules( $$$$ ) { add_rule $chainref, "-j $default" if $default && $default ne 'none'; log_rule $loglevel , $chainref , $target , '' if $loglevel ne ''; fatal_error "Null target in policy_rules()" unless $target; - add_rule $chainref , ( '-j ' . ( $target eq 'REJECT' ? 'reject' : $target ) ) unless $target eq 'CONTINUE'; + if ( $target eq 'REJECT' ) { + $target = 'reject'; + } elsif ( $target =~ /^NFQUEUE/ ) { + my $queue = ( split( '/', $target) )[1] || 0; + $target = "NFQUEUE --queue-num $queue"; + } + + add_rule( $chainref , "-j $target" ) unless $target eq 'CONTINUE'; } } @@ -305,7 +337,7 @@ sub default_policy( $$$ ) { if ( $chainref eq $policyref ) { policy_rules $chainref , $policy, $loglevel , $default; } else { - if ( $policy eq 'ACCEPT' || $policy eq 'QUEUE' ) { + if ( $policy eq 'ACCEPT' || $policy eq 'QUEUE' || $policy =~ /^NFQUEUE/ ) { if ( $synparams ) { report_syn_flood_protection; policy_rules $chainref , $policy , $loglevel , $default; @@ -374,6 +406,8 @@ sub apply_policy_rules() { sub complete_standard_chain ( $$$ ) { my ( $stdchainref, $zone, $zone2 ) = @_; + add_rule $stdchainref, '-m state --state ESTABLISHED,RELATED -j ACCEPT' unless $config{FASTACCEPT}; + run_user_exit $stdchainref; my $ruleschainref = $filter_table->{"${zone}2${zone2}"}; diff --git a/Shorewall-perl/Shorewall/Providers.pm b/Shorewall-perl/Shorewall/Providers.pm index 2073f561e..e718331dc 100644 --- a/Shorewall-perl/Shorewall/Providers.pm +++ b/Shorewall-perl/Shorewall/Providers.pm @@ -316,8 +316,9 @@ sub add_an_rtrule( $$$$ ) { if ( "\L$provider" =~ /^(0x[a-f0-9]+|0[0-7]*|[0-9]*)$/ ) { my $provider_number = numeric_value $provider; - for my $provider ( keys %providers ) { - if ( $providers{$provider}{number} == $provider_number ) { + for ( keys %providers ) { + if ( $providers{$_}{number} == $provider_number ) { + $provider = $_; $found = 1; last; } diff --git a/Shorewall-perl/Shorewall/Rules.pm b/Shorewall-perl/Shorewall/Rules.pm index a92deda6e..07a6974be 100644 --- a/Shorewall-perl/Shorewall/Rules.pm +++ b/Shorewall-perl/Shorewall/Rules.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( process_tos dump_rule_chains ); our @EXPORT_OK = qw( process_rule process_rule1 initialize ); -our $VERSION = 4.02; +our $VERSION = 4.03; # # Keep track of chains for the /var/lib/shorewall[-lite]/chains file @@ -109,8 +109,8 @@ sub process_tos() { my ($src, $dst, $proto, $sports, $ports , $tos, $mark ) = split_line 6, 7, 'tos file entry'; - fatal_error "TOS field required" unless $tos ne '-'; - + fatal_error "A value must be supplied in the TOS column" if $tos eq '-'; + if ( defined ( my $tosval = $tosoptions{"\L$tos"} ) ) { $tos = $tosval; } elsif ( numeric_value( $tos ) > 0x1e ) { @@ -501,6 +501,13 @@ sub add_common_rules() { my $list; my $chain; + if ( $config{FASTACCEPT} ) { + for $chain qw( INPUT FORWARD OUTPUT ) { + $chainref = $filter_table->{$chain}; + add_rule( $chainref , "-m state --state ESTABLISHED,RELATED -j ACCEPT" ); + } + } + my $rejectref = new_standard_chain 'reject'; $level = $config{BLACKLIST_LOGLEVEL}; @@ -533,10 +540,10 @@ sub add_common_rules() { add_rule_pair $chainref, '-m addrtype --src-type BROADCAST ', 'DROP', $config{SMURF_LOG_LEVEL} ; } else { add_command $chainref, 'for address in $ALL_BCASTS; do'; - push_cmd_mode $chainref; + incr_cmd_level $chainref; log_rule( $config{SMURF_LOG_LEVEL} , $chainref, 'DROP', '-s $address ' ); add_rule $chainref, '-s $address -j DROP'; - pop_cmd_mode $chainref; + decr_cmd_level $chainref; add_command $chainref, 'done'; } @@ -546,9 +553,9 @@ sub add_common_rules() { add_rule $rejectref , '-m addrtype --src-type BROADCAST -j DROP'; } else { add_command $rejectref, 'for address in $ALL_BCASTS; do'; - push_cmd_mode $rejectref; + incr_cmd_level $rejectref; add_rule $rejectref, '-d $address -j DROP'; - pop_cmd_mode $rejectref; + decr_cmd_level $rejectref; add_command $rejectref, 'done'; } @@ -967,6 +974,14 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $current_param = pop @param_stack if $param ne ''; return; + + } elsif ( $actiontype & NFQ ) { + require_capability( 'NFQUEUE_TARGET', 'NFQUEUE Rules', '' ); + $param = $param eq '' ? 0 : numeric_value( $param ); + fatal_error "Invalid value ($param) for NFQUEUE queue number" if $param > 65535; + $action = "NFQUEUE/$param"; + } else { + fatal_error "The $basictarget TARGET does not accept a parameter" unless $param eq ''; } # # We can now dispense with the postfix characters @@ -1110,7 +1125,6 @@ sub process_rule1 ( $$$$$$$$$$$ ) { my $servport = $serverport ne '' ? $serverport : $ports; fatal_error "A server must be specified in the DEST column in $action rules" unless ( $actiontype & REDIRECT ) || $server ne ALLIPv4; - fatal_error "Invalid server ($server)" if $server =~ /:/; # # Generate the target # @@ -1118,6 +1132,17 @@ sub process_rule1 ( $$$$$$$$$$$ ) { if ( $actiontype & REDIRECT ) { $target = '-j REDIRECT --to-port ' . ( $serverport ne '' ? $serverport : $ports ); + if ( $origdest eq '' || $origdest eq '-' ) { + $origdest = ALLIPv4; + } elsif ( $origdest eq 'detect' ) { + if ( $config{DETECT_DNAT_IPADDRS} && $sourcezone ne $firewall_zone ) { + my $interfacesref = $zones{$sourcezone}{interfaces}; + my @interfaces = keys %$interfacesref; + $origdest = @interfaces ? "detect:@interfaces" : ALLIPv4; + } else { + $origdest = ALLIPv4; + } + } } else { if ( $action eq 'SAME' ) { fatal_error 'Port mapping not allowed in SAME rules' if $serverport; @@ -1135,7 +1160,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { } unless ( $origdest && $origdest ne '-' && $origdest ne 'detect' ) { - if ( $config{DETECT_DNAT_IPADDRS} ) { + if ( $config{DETECT_DNAT_IPADDRS} && $sourcezone ne $firewall_zone ) { my $interfacesref = $zones{$sourcezone}{interfaces}; my @interfaces = keys %$interfacesref; $origdest = @interfaces ? "detect:@interfaces" : ALLIPv4; @@ -1144,6 +1169,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { } } } + # # And generate the nat table rule(s) # @@ -1217,7 +1243,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $source , $dest , $origdest , - "-j $action " , + $actiontype & NFQ ? "-j NFQUEUE --queue-num $param " : "-j $action " , $loglevel , $action , '' ); @@ -1849,25 +1875,58 @@ sub generate_matrix() { } } -sub setup_mss( $ ) { - my $clampmss = $_[0]; +sub setup_mss( ) { + my $clampmss = $config{CLAMPMSS}; my $option; my $match = ''; + my $chainref = $filter_table->{FORWARD}; - if ( "\L$clampmss" eq 'yes' ) { - $option = '--clamp-mss-to-pmtu'; - } else { - $match = "-m tcpmss --mss $clampmss: " if $capabilities{TCPMSS_MATCH}; - $option = "--set-mss $clampmss"; + if ( $clampmss ) { + if ( "\L$clampmss" eq 'yes' ) { + $option = '--clamp-mss-to-pmtu'; + } else { + $match = "-m tcpmss --mss $clampmss: " if $capabilities{TCPMSS_MATCH}; + $option = "--set-mss $clampmss"; + } + + $match .= '-m policy --pol none --dir out ' if $capabilities{POLICY_MATCH}; } - add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS $option"; + my $interfaces = find_interfaces_by_option( 'mss' ); + + if ( @$interfaces ) { + # + # Since we will need multiple rules, we create a separate chain + # + $chainref = new_chain 'filter', 'settcpmss'; + # + # Send all forwarded SYN packets to the 'settcpmss' chain + # + add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN -j settcpmss"; + + my $in_match = ''; + my $out_match = ''; + + if ( $capabilities{POLICY_MATCH} ) { + $in_match = '-m policy --pol none --dir in '; + $out_match = '-m policy --pol none --dir out '; + } + + for ( @$interfaces ) { + my $mss = $interfaces{$_}{options}{mss}; + my $mssmatch = $capabilities{TCPMSS_MATCH} ? "-m tcpmss --mss $mss: " : ''; + add_rule $chainref, "-o $_ -p tcp --tcp-flags SYN,RST SYN ${mssmatch}${out_match}-j TCPMSS --set-mss $mss"; + add_rule $chainref, "-o $_ -j RETURN" if $clampmss; + add_rule $chainref, "-i $_ -p tcp --tcp-flags SYN,RST SYN ${mssmatch}${in_match}-j TCPMSS --set-mss $mss"; + add_rule $chainref, "-i $_ -j RETURN" if $clampmss; + } + } + + add_rule $chainref , "-p tcp --tcp-flags SYN,RST SYN ${match}-j TCPMSS $option" if $clampmss; } sub dump_rule_chains() { - for my $arrayref ( @rule_chains ) { - emit_unindented "@$arrayref"; - } + emit_unindented "@$_" for ( @rule_chains ); } 1; diff --git a/Shorewall-perl/Shorewall/Tc.pm b/Shorewall-perl/Shorewall/Tc.pm index e931f3811..a0f9ba95e 100644 --- a/Shorewall-perl/Shorewall/Tc.pm +++ b/Shorewall-perl/Shorewall/Tc.pm @@ -39,7 +39,7 @@ use strict; our @ISA = qw(Exporter); our @EXPORT = qw( setup_tc ); our @EXPORT_OK = qw( process_tc_rule initialize ); -our $VERSION = 4.02; +our $VERSION = 4.03; our %tcs = ( T => { chain => 'tcpost', connmark => 0, @@ -184,7 +184,7 @@ sub process_tc_rule( $$$$$$$$$$ ) { my $tcsref; my $connmark = 0; my $classid = 0; - my $device; + my $device = ''; if ( $source ) { if ( $source eq $firewall_zone ) { @@ -268,21 +268,22 @@ sub process_tc_rule( $$$$$$$$$$ ) { } } - if ( my $result = expand_rule( - ensure_chain( 'mangle' , $chain ) , - NO_RESTRICT , - do_proto( $proto, $ports, $sports) . do_test( $testval, $mask ) . do_tos( $tos ) , - $source , - $dest , + if ( ( my $result = expand_rule( + ensure_chain( 'mangle' , $chain ) , + NO_RESTRICT , + do_proto( $proto, $ports, $sports) . do_test( $testval, $mask ) . do_tos( $tos ) , + $source , + $dest , + '' , + "-j $target $mark" , '' , - "-j $target $mark" , - '' , - '' , - '' ) ) { + '' , + '' ) ) + && $device ) { # # expand_rule() returns destination device if any # - fatal_error "Class Id $original_mark is not associated with device $result" if $config{TC_ENABLED} eq 'internal' && $classid && $device ne $result; + fatal_error "Class Id $original_mark is not associated with device $result" if $device ne $result; } progress_message " TC Rule \"$currentline\" $done"; diff --git a/Shorewall-perl/Shorewall/Zones.pm b/Shorewall-perl/Shorewall/Zones.pm index 330115acf..197a8e71b 100644 --- a/Shorewall-perl/Shorewall/Zones.pm +++ b/Shorewall-perl/Shorewall/Zones.pm @@ -37,6 +37,7 @@ our @EXPORT = qw( NOTHING IPSECPROTO IPSECMODE + numeric_value determine_zones zone_report dump_zone_contents @@ -59,7 +60,7 @@ our @EXPORT = qw( NOTHING @bridges ); our @EXPORT_OK = qw( initialize ); -our $VERSION = 4.01; +our $VERSION = 4.03; # # IPSEC Option types @@ -76,7 +77,7 @@ use constant { NOTHING => 'NOTHING', # # @zones contains the ordered list of zones with sub-zones appearing before their parents. # -# %zones{ => {type = > +# %zones{ => {type = > 'firewall', 'ipv4', 'ipsec4', 'bport4'; # options => { complex => 0|1 # in_out => < policy match string > # in => < policy match string > @@ -110,16 +111,6 @@ our %reservedName = ( all => 1, SOURCE => 1, DEST => 1 ); -se constant ( ZT_IPV4 => 1, - ZT_IPSEC => 2, - ZT_BPORT => 4, - ZT_IPV6 => 8, - ZT_FIREWALL => 16, - ZT_IPSEC4 => ZT_IPV4 | ZT_IPSEC - ZT_IPSEC6 => ZT_IPV6 | ZT_IPSEC - ZT_BPORT4 => ZT_IPV4 | ZT_BPORT - ZT_BPORT6 => ZT_IPV6 | ZT_BPORT - ); # # Interface Table. # @@ -162,6 +153,15 @@ INIT { initialize; } +# +# Convert value to decimal number +# +sub numeric_value ( $ ) { + my $mark = $_[0]; + fatal_error "Invalid Numeric Value ($mark)" unless "\L$mark" =~ /^(0x[a-f0-9]+|0[0-7]*|[1-9]\d*)$/; + $mark =~ /^0/ ? oct $mark : $mark; +} + # # Parse the passed option list and return a reference to a hash as follows: # @@ -219,7 +219,7 @@ sub parse_zone_option_list($$) if ( $key{$e} ) { $h{$e} = $val; } else { - fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype & ZT_IPSEC; + fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype eq 'ipsec4'; $options .= $invert; $options .= "--$e "; $options .= "$val "if defined $val; @@ -261,7 +261,7 @@ sub determine_zones() for my $p ( @parents ) { fatal_error "Invalid Parent List ($2)" unless $p; fatal_error "Unknown parent zone ($p)" unless $zones{$p}; - fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} & ZT_FIREWALL; + fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} eq 'firewall'; push @{$zones{$p}{children}}, $zone; } } @@ -273,20 +273,20 @@ sub determine_zones() $type = "ipv4" unless $type; if ( $type =~ /ipv4/i ) { - $type = ZT_IPV4; + $type = 'ipv4'; } elsif ( $type =~ /^ipsec4?$/i ) { - $type = ZT_IPSEC4; + $type = 'ipsec4'; } elsif ( $type =~ /^bport4?$/i ) { warning_message "Bridge Port zones should have a parent zone" unless @parents; - $type = ZT_BPORT4; + $type = 'bport4'; } elsif ( $type eq 'firewall' ) { fatal_error 'Firewall zone may not be nested' if @parents; fatal_error "Only one firewall zone may be defined ($zone)" if $firewall_zone; $firewall_zone = $zone; $ENV{FW} = $zone; - $type = ZT_FIREWALL; + $type = "firewall"; } elsif ( $type eq '-' ) { - $type = ZT_IPV4; + $type = 'ipv4'; } else { fatal_error "Invalid zone type ($type)" ; } @@ -302,7 +302,7 @@ sub determine_zones() options => { in_out => parse_zone_option_list( $options || '', $type ) , in => parse_zone_option_list( $in_options || '', $type ) , out => parse_zone_option_list( $out_options || '', $type ) , - complex => ($type & ZT_IPSEC || $options || $in_options || $out_options ? 1 : 0) } , + complex => ($type eq 'ipsec4' || $options || $in_options || $out_options ? 1 : 0) } , interfaces => {} , children => [] , hosts => {} @@ -337,22 +337,12 @@ sub determine_zones() # sub haveipseczones() { for my $zoneref ( values %zones ) { - return 1 if $zoneref->{type} & ZT_IPSEC; + return 1 if $zoneref->{type} eq 'ipsec4'; } 0; } -my @typenames = ( Untyped, #0 - firewall, #1 - ipv4, #2 - Invalid, #3 - Invalid, #4 - Invalid, #5 - ipsec4, #6 - Invalid, #7 - Invalid, #8 - # # Report about zones. # @@ -551,9 +541,10 @@ sub validate_interfaces_file( $ ) use constant { SIMPLE_IF_OPTION => 1, BINARY_IF_OPTION => 2, ENUM_IF_OPTION => 3, - MASK_IF_OPTION => 3, + NUMERIC_IF_OPTION => 4, + MASK_IF_OPTION => 7, - IF_OPTION_ZONEONLY => 4 }; + IF_OPTION_ZONEONLY => 8 }; my %validoptions = (arp_filter => BINARY_IF_OPTION, arp_ignore => ENUM_IF_OPTION, @@ -572,6 +563,7 @@ sub validate_interfaces_file( $ ) sourceroute => BINARY_IF_OPTION, tcpflags => SIMPLE_IF_OPTION, upnp => SIMPLE_IF_OPTION, + mss => NUMERIC_IF_OPTION, ); my $fn = open_file 'interfaces'; @@ -701,6 +693,9 @@ sub validate_interfaces_file( $ ) } else { fatal_error "Internal Error in validate_interfaces_file"; } + } elsif ( $type == NUMERIC_IF_OPTION ) { + fatal_error "The $option option requires a value" unless defined $value; + $options{$option} = numeric_value $value; } } diff --git a/Shorewall-perl/install.sh b/Shorewall-perl/install.sh index e73c57c61..1f6163252 100755 --- a/Shorewall-perl/install.sh +++ b/Shorewall-perl/install.sh @@ -22,7 +22,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA # -VERSION=4.0.2 +VERSION=4.0.3 usage() # $1 = exit status { diff --git a/Shorewall-perl/prog.header b/Shorewall-perl/prog.header index e275fbabd..08d5e6fd1 100644 --- a/Shorewall-perl/prog.header +++ b/Shorewall-perl/prog.header @@ -540,7 +540,7 @@ find_first_interface_address_if_any() # $1 = interface # interface_is_usable() # $1 = interface { - interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ] + interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ] && run_isusable_exit $1 } # diff --git a/Shorewall-perl/shorewall-perl.spec b/Shorewall-perl/shorewall-perl.spec index aef481099..f33d1b09b 100644 --- a/Shorewall-perl/shorewall-perl.spec +++ b/Shorewall-perl/shorewall-perl.spec @@ -1,5 +1,5 @@ %define name shorewall-perl -%define version 4.0.2 +%define version 4.0.3 %define release 1 Summary: Shoreline Firewall Perl-based compiler. @@ -72,6 +72,8 @@ fi %doc COPYING releasenotes.txt %changelog +* Mon Aug 13 2007 Tom Eastep tom@shorewall.net +- Updated to 4.0.3-1 * Thu Aug 09 2007 Tom Eastep tom@shorewall.net - Updated to 4.0.2-1 * Sat Jul 21 2007 Tom Eastep tom@shorewall.net