diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/Perl/Shorewall/Chains.pm shorewall-4.4.19.2/Perl/Shorewall/Chains.pm --- shorewall-4.4.19.1/Perl/Shorewall/Chains.pm 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/Perl/Shorewall/Chains.pm 2011-05-05 16:18:04.000000000 -0700 @@ -2870,7 +2870,7 @@ add_commands( $chainref , "fi\n" ); } -sub mysplit( $ ); +sub mysplit( $$ ); # # Match a Source. @@ -2901,7 +2901,7 @@ if ( $net =~ /^\+\[(.+)\]$/ ) { my $result = ''; - my @sets = mysplit $1; + my @sets = mysplit $1, 1; require_capability 'KLUDGEFREE', 'Multiple ipset matches', '' if @sets > 1; @@ -2951,7 +2951,7 @@ if ( $net =~ /^\+\[(.+)\]$/ ) { my $result = ''; - my @sets = mysplit $1; + my @sets = mysplit $1, 1; require_capability 'KLUDGEFREE', 'Multiple ipset matches', '' if @sets > 1; @@ -3229,10 +3229,14 @@ # Split a comma-separated source or destination host list but keep [...] together. Used for spliting address lists # where an element of the list might be +ipset[flag,...] or +[ipset[flag,...],...] # -sub mysplit( $ ) { - my @input = split_list $_[0], 'host'; +sub mysplit( $$ ) { + my ( $input, $loose ) = @_; - return @input unless $_[0] =~ /\[/; + my @input = split_list $input, 'host'; + + return @input unless $input =~ /\[/; + + my $exclude = 0; my @result; @@ -3245,7 +3249,14 @@ $element .= ( ',' . shift @input ); } + unless ( $loose ) { + fatal_error "Invalid host list ($input)" if $exclude && $element =~ /!/; + } + + $exclude ||= $element =~ /^!/ || $element =~ /\]!/; fatal_error "Mismatched [...] ($element)" unless $element =~ tr/[/[/ == $element =~ tr/]/]/; + } else { + $exclude ||= $element =~ /!/; } push @result, $element; @@ -3627,7 +3638,7 @@ my $nets = ''; my $excl = ''; - my @nets = mysplit $list; + my @nets = mysplit $list, 0; for ( @nets ) { if ( /!/ ) { @@ -3943,7 +3954,7 @@ } unless ( $onets ) { - my @oexcl = mysplit $oexcl; + my @oexcl = mysplit $oexcl, 0; if ( @oexcl == 1 ) { $rule .= match_orig_dest( "!$oexcl" ); $oexcl = ''; @@ -3961,7 +3972,7 @@ ( $inets, $iexcl ) = handle_network_list( $inets, 'SOURCE' ); unless ( $inets || $iexcl =~ /^\+\[/ || ( $iiface && $restriction & POSTROUTE_RESTRICT ) ) { - my @iexcl = mysplit $iexcl; + my @iexcl = mysplit $iexcl, 1; if ( @iexcl == 1 ) { $rule .= match_source_net "!$iexcl" , $restriction; $iexcl = ''; @@ -3979,7 +3990,7 @@ ( $dnets, $dexcl ) = handle_network_list( $dnets, 'DEST' ); unless ( $dnets || $dexcl =~ /^\+\[/ ) { - my @dexcl = mysplit $dexcl; + my @dexcl = mysplit $dexcl, 1; if ( @dexcl == 1 ) { $rule .= match_dest_net "!$dexcl"; $dexcl = ''; @@ -4018,19 +4029,19 @@ # my $exclude = '-j MARK --or-mark ' . in_hex( $globals{EXCLUSION_MASK} ); - for ( mysplit $iexcl ) { + for ( mysplit $iexcl, 0 ) { my $cond = conditional_rule( $chainref, $_ ); add_rule $chainref, ( match_source_net $_ , $restriction, $mac ) . $exclude; conditional_rule_end( $chainref ) if $cond; } - for ( mysplit $dexcl ) { + for ( mysplit $dexcl, 0 ) { my $cond = conditional_rule( $chainref, $_ ); add_rule $chainref, ( match_dest_net $_ ) . $exclude; conditional_rule_end( $chainref ) if $cond; } - for ( mysplit $oexcl ) { + for ( mysplit $oexcl, 0 ) { my $cond = conditional_rule( $chainref, $_ ); add_rule $chainref, ( match_orig_dest $_ ) . $exclude; conditional_rule_end( $chainref ) if $cond; @@ -4049,19 +4060,19 @@ # # Use the current rule and send all possible matches to the exclusion chain # - for my $onet ( mysplit $onets ) { + for my $onet ( mysplit $onets , 0 ) { my $cond = conditional_rule( $chainref, $onet ); $onet = match_orig_dest $onet; - for my $inet ( mysplit $inets ) { + for my $inet ( mysplit $inets , 0 ) { my $cond = conditional_rule( $chainref, $inet ); my $source_match = match_source_net( $inet, $restriction, $mac ) if have_capability( 'KLUDGEFREE' ); - for my $dnet ( mysplit $dnets ) { + for my $dnet ( mysplit $dnets , 0 ) { $source_match = match_source_net( $inet, $restriction, $mac ) unless have_capability( 'KLUDGEFREE' ); add_jump( $chainref, $echainref, 0, join( '', $rule, $source_match, match_dest_net( $dnet ), $onet ), 1 ); } @@ -4074,19 +4085,19 @@ # # Generate RETURNs for each exclusion # - for ( mysplit $iexcl ) { + for ( mysplit $iexcl , 0 ) { my $cond = conditional_rule( $echainref, $_ ); add_rule $echainref, ( match_source_net $_ , $restriction, $mac ) . '-j RETURN'; conditional_rule_end( $echainref ) if $cond; } - for ( mysplit $dexcl ) { + for ( mysplit $dexcl , 0 ) { my $cond = conditional_rule( $echainref, $_ ); add_rule $echainref, ( match_dest_net $_ ) . '-j RETURN'; conditional_rule_end( $echainref ) if $cond; } - for ( mysplit $oexcl ) { + for ( mysplit $oexcl , 0 ) { my $cond = conditional_rule( $echainref, $_ ); add_rule $echainref, ( match_orig_dest $_ ) . '-j RETURN'; conditional_rule_end( $echainref ) if $cond; @@ -4116,19 +4127,19 @@ # # No non-trivial exclusions or we're using marks to handle them # - for my $onet ( mysplit $onets ) { + for my $onet ( mysplit $onets , 0 ) { my $cond = conditional_rule( $chainref, $onet ); $onet = match_orig_dest $onet; - for my $inet ( mysplit $inets ) { + for my $inet ( mysplit $inets , 0 ) { my $source_match; my $cond = conditional_rule( $chainref, $inet ); $source_match = match_source_net( $inet, $restriction, $mac ) if have_capability( 'KLUDGEFREE' ); - for my $dnet ( mysplit $dnets ) { + for my $dnet ( mysplit $dnets , 0 ) { $source_match = match_source_net( $inet, $restriction, $mac ) unless have_capability( 'KLUDGEFREE' ); my $dest_match = match_dest_net( $dnet ); my $matches = join( '', $rule, $source_match, $dest_match, $onet ); diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/Perl/Shorewall/Config.pm shorewall-4.4.19.2/Perl/Shorewall/Config.pm --- shorewall-4.4.19.1/Perl/Shorewall/Config.pm 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/Perl/Shorewall/Config.pm 2011-05-05 16:18:04.000000000 -0700 @@ -61,6 +61,7 @@ disable_script numeric_value numeric_value1 + normalize_hex hex_value in_hex in_hex2 @@ -411,7 +412,7 @@ EXPORT => 0, STATEMATCH => '-m state --state', UNTRACKED => 0, - VERSION => "4.4.19.1", + VERSION => "4.4.19.2", CAPVERSION => 40417 , ); # @@ -820,6 +821,16 @@ } # +# Strip off superfluous leading zeros from a hex number +# +sub normalize_hex( $ ) { + my $val = lc shift; + + $val =~ s/^0// while $val =~ /^0/ && length $val > 1; + $val; +} + +# # Return the argument expressed in Hex # sub in_hex( $ ) { diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/Perl/Shorewall/Rules.pm shorewall-4.4.19.2/Perl/Shorewall/Rules.pm --- shorewall-4.4.19.1/Perl/Shorewall/Rules.pm 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/Perl/Shorewall/Rules.pm 2011-05-05 16:18:04.000000000 -0700 @@ -2013,6 +2013,7 @@ $loglevel = ''; $dest = $server; $action = 'ACCEPT'; + $origdest = ALLIP if $origdest =~ /[+]/; } } elsif ( $actiontype & NONAT ) { # diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/Perl/Shorewall/Tc.pm shorewall-4.4.19.2/Perl/Shorewall/Tc.pm --- shorewall-4.4.19.1/Perl/Shorewall/Tc.pm 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/Perl/Shorewall/Tc.pm 2011-05-05 16:18:04.000000000 -0700 @@ -252,10 +252,12 @@ require_capability ('CONNMARK' , "CONNMARK Rules", '' ) if $connmark; } else { - fatal_error "Invalid MARK ($originalmark)" unless $mark =~ /^([0-9]+|0x[0-9a-f]+)$/ and $designator =~ /^([0-9]+|0x[0-9a-f]+)$/; + fatal_error "Invalid MARK ($originalmark)" unless $mark =~ /^([0-9a-fA-F]+)$/ and $designator =~ /^([0-9a-fA-F]+)$/; if ( $config{TC_ENABLED} eq 'Internal' || $config{TC_ENABLED} eq 'Shared' ) { + $originalmark = join( ':', normalize_hex( $mark ), normalize_hex( $designator ) ); fatal_error "Unknown Class ($originalmark)}" unless ( $device = $classids{$originalmark} ); + fatal_error "IFB Classes may not be specified in tcrules" if @{$tcdevices{$device}{redirected}}; } $chain = 'tcpost'; @@ -602,15 +604,16 @@ fatal_error "Invalid NUMBER:INTERFACE ($device:$number:$rest)" if defined $rest; if ( defined $number ) { + $number = normalize_hex( $number ); $devnumber = hex_value( $number ); - fatal_error "Invalid interface NUMBER ($number)" unless defined $devnumber && $devnumber; + fatal_error "Invalid device NUMBER ($number)" unless defined $devnumber && $devnumber && $devnumber < 256; fatal_error "Duplicate interface number ($number)" if defined $devnums[ $devnumber ]; $devnum = $devnumber if $devnumber > $devnum; } else { fatal_error "Missing interface NUMBER"; } - } else { - $devnumber = ++$devnum; + } elsif ( ( $devnumber = ++$devnum ) > 255 ) { + fatal_error "Attempting to assign a device number > 255"; } $devnums[ $devnumber ] = $device; @@ -745,7 +748,6 @@ } ( $dev , $devref ); - } sub validate_tc_class( ) { @@ -761,7 +763,7 @@ ( $device, my ($number, $subnumber, $rest ) ) = split /:/, $device, 4; fatal_error "Invalid INTERFACE:CLASS ($devclass)" if defined $rest; - if ( $device =~ /^(\d+|0x[\da-fA-F]+)$/ ) { + if ( $device =~ /^[\da-fA-F]+$/ && ! $tcdevices{$device} ) { ( $number , $classnumber ) = ( hex_value $device, hex_value $number ); ( $device , $devref) = dev_by_number( $number ); } else { @@ -777,7 +779,8 @@ $classnumber = hex_value $subnumber; } - fatal_error "Invalid interface/class number ($devclass)" unless defined $classnumber && $classnumber; + fatal_error "Invalid interface/class number ($devclass)" unless defined $classnumber && $classnumber && $classnumber < 0x8000; + fatal_error "Reserved class number (1)" if $classnumber == 1; fatal_error "Duplicate interface:class number ($number:$classnumber}" if $tcclasses{$device}{$classnumber}; } else { fatal_error "Missing interface NUMBER"; @@ -976,9 +979,15 @@ my ( $ip, $ip32, $prio , $lo ) = $family == F_IPV4 ? ('ip', 'ip', 10, 2 ) : ('ipv6', 'ip6', 11 , 4 ); - ( $device , my $devref ) = dev_by_number( $device ); + my $devref; - my $devnum = $devref->{number}; + if ( $device =~ /^[\da-fA-F]+$/ && ! $tcdevices{$device} ) { + ( $device, $devref ) = dev_by_number( hex_value( $device ) ); + } else { + ( $device , $devref ) = dev_by_number( $device ); + } + + my $devnum = in_hexp $devref->{number}; my $tcref = $tcclasses{$device}; @@ -1051,7 +1060,7 @@ if ( $portlist eq '-' && $sportlist eq '-' ) { emit( "\nrun_tc $rule\\" , - " flowid $devref->{number}:$class" , + " flowid $devnum:$class" , '' ); } else { fatal_error "Ports may not be specified without a PROTO" unless $protonumber; @@ -1113,7 +1122,7 @@ emit( "\nrun_tc $rule\\" , " $rule1\\" , - " flowid $devref->{number}:$class" ); + " flowid $devnum:$class" ); } } } else { @@ -1131,7 +1140,7 @@ $rule1 .= "\\\n match icmp code $icmpcode 0xff" if defined $icmpcode; emit( "\nrun_tc ${rule}\\" , "$rule1\\" , - " flowid $devref->{number}:$class" ); + " flowid $devnum:$class" ); } elsif ( $protonumber == IPv6_ICMP ) { fatal_error "IPv6 ICMP not allowed with IPv4" unless $family == F_IPV4; fatal_error "SOURCE PORT(S) are not allowed with IPv6 ICMP" if $sportlist ne '-'; @@ -1142,7 +1151,7 @@ $rule1 .= "\\\n match icmp6 code $icmpcode 0xff" if defined $icmpcode; emit( "\nrun_tc ${rule}\\" , "$rule1\\" , - " flowid $devref->{number}:$class" ); + " flowid $devnum:$class" ); } else { my @portlist = expand_port_range $protonumber , $portrange; @@ -1162,7 +1171,7 @@ if ( $sportlist eq '-' ) { emit( "\nrun_tc ${rule}\\" , " $rule1\\" , - " flowid $devref->{number}:$class" ); + " flowid $devnum:$class" ); } else { for my $sportrange ( split_list $sportlist , 'port list' ) { my @sportlist = expand_port_range $protonumber , $sportrange; @@ -1183,7 +1192,7 @@ emit( "\nrun_tc ${rule}\\", " $rule1\\" , " $rule2\\" , - " flowid $devref->{number}:$class" ); + " flowid $devnum:$class" ); } } } @@ -1376,6 +1385,8 @@ my $devnum = in_hexp $devref->{number}; my $r2q = int calculate_r2q $devref->{out_bandwidth}; + fatal_error "No default class defined for device $device" unless $devref->{default}; + $device = physical_name $device; my $dev = chain_base( $device ); @@ -1513,7 +1524,7 @@ # # options # - emit "run_tc filter add dev $device parent $devref->{number}:0 protocol ip prio " . ( $priority | 10 ) ." u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid $classid" if $tcref->{tcp_ack}; + emit "run_tc filter add dev $device parent $devicenumber:0 protocol ip prio " . ( $priority | 10 ) ." u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid $classid" if $tcref->{tcp_ack}; for my $tospair ( @{$tcref->{tos}} ) { my ( $tos, $mask ) = split q(/), $tospair; diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/changelog.txt shorewall-4.4.19.2/changelog.txt --- shorewall-4.4.19.1/changelog.txt 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/changelog.txt 2011-05-05 16:18:04.000000000 -0700 @@ -1,3 +1,12 @@ +Changes in Shorewall 4.4.19.2 + +1) Restore the ability to have IPSET names in the ORIGINAL DEST column + of a DNAT or REDIRECT rule. + +2) Correct several complex TC issues reported by Mr Dash4. + +3) Detect double exclusion involving ipset expressions. + Changes in Shorewall 4.4.19.1 1) Eliminate silly duplicate rule when stopped. diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/install.sh shorewall-4.4.19.2/install.sh --- shorewall-4.4.19.1/install.sh 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/install.sh 2011-05-05 16:18:04.000000000 -0700 @@ -22,7 +22,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -VERSION=4.4.19.1 +VERSION=4.4.19.2 usage() # $1 = exit status { diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/releasenotes.txt shorewall-4.4.19.2/releasenotes.txt --- shorewall-4.4.19.1/releasenotes.txt 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/releasenotes.txt 2011-05-05 16:18:04.000000000 -0700 @@ -1,5 +1,5 @@ ---------------------------------------------------------------------------- - S H O R E W A L L 4 . 4 . 1 9 . 1 + S H O R E W A L L 4 . 4 . 1 9 . 2 ---------------------------------------------------------------------------- I. PROBLEMS CORRECTED IN THIS RELEASE @@ -13,6 +13,58 @@ I. P R O B L E M S C O R R E C T E D I N T H I S R E L E A S E ---------------------------------------------------------------------------- +4.4.19.2 + +1) In Shorewall-shell, there was the ability to specify IPSET names in + the ORIGINAL DEST column of DNAT and REDIRECT rules. That ability, + inadvertently dropped in Shorewall-perl, has been restored. + + CAUTION: When an IPSET is used in this way, the server port is + opened from the SOURCE zone. + + Example: + + DNAT net dmz:10.1.1.2 tcp 80 - +foo + + will implicitly add this rule + + ACCEPT net dmz:10.1.1.2 tcp 80 + +2) Several problems with complex TC have been corrected: + + a) The following entry in /etc/shorewall/tcclasses + + A:1 - 10*full/100:50ms 20*full/100 1 tcp-ack + + produced this error: + + ERROR: Unknown INTERFACE (A) : /etc/shorewall/tcclasses + + This has been corrected. + + b) Shorewall reserves class number 1 for the root class of the + queuing discipline. Definining class 1 in + /etc/shorewall/tcclasses was previoulsly escaping detection by + the compiler, resulting in a run-time error. + + c) The compiler did not complain if a CLASSID specified in the MARK + column of tcrules referred to an IFB class. Such a rule would be + nonsensical since packets are passed through the IFB before + they are passed through any marking rules. Such a configuration + now results in a compilation error. + + d) Where there are more than 10 tcdevices, tcfilter entries could + generate invalid rules. + +3) Double exclusion involving ipset lists was previously not detected, + resulting in anomalous behavior. + + Example: + + ACCEPT:info $FW net:!10.1.0.7,10.1.0.9,+[!my-host[src]]] + + Such cases now result in a compilation error. + 4.4.19.1 1) A duplicate ACCEPT rule in the INPUT chain has been eliminated when diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/shorewall.spec shorewall-4.4.19.2/shorewall.spec --- shorewall-4.4.19.1/shorewall.spec 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/shorewall.spec 2011-05-05 16:18:04.000000000 -0700 @@ -1,6 +1,6 @@ %define name shorewall %define version 4.4.19 -%define release 1 +%define release 2 Summary: Shoreline Firewall is an iptables-based firewall for Linux systems. Name: %{name} @@ -109,6 +109,8 @@ %doc COPYING INSTALL changelog.txt releasenotes.txt Contrib/* Samples %changelog +* Sat Apr 16 2011 Tom Eastep tom@shorewall.net +- Updated to 4.4.19-2 * Wed Apr 13 2011 Tom Eastep tom@shorewall.net - Updated to 4.4.19-1 * Sat Apr 09 2011 Tom Eastep tom@shorewall.net diff -Naurdw -X /Users/teastep/bin/exclude.txt shorewall-4.4.19.1/uninstall.sh shorewall-4.4.19.2/uninstall.sh --- shorewall-4.4.19.1/uninstall.sh 2011-04-15 11:15:32.000000000 -0700 +++ shorewall-4.4.19.2/uninstall.sh 2011-05-05 16:18:04.000000000 -0700 @@ -26,7 +26,7 @@ # You may only use this script to uninstall the version # shown below. Simply run this script to remove Shorewall Firewall -VERSION=4.4.19.1 +VERSION=4.4.19.2 usage() # $1 = exit status {