diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index bac44d1bd..6813bf7d0 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -147,31 +147,21 @@ our %EXPORT_TAGS = ( clearrule port_count do_proto - do_iproto do_mac do_imac verify_mark verify_small_mark validate_mark do_test - do_itest do_ratelimit - do_iratelimit do_connlimit do_time - do_itime do_user - do_iuser do_length - do_ilength do_tos - do_itos do_connbytes - do_iconnbytes do_helper - do_ihelper do_headers - do_iheaders have_ipset_rules record_runtime_address conditional_rule @@ -442,41 +432,34 @@ use constant { UNIQUE => 1, TARGET => 2, EXCLUSIVE => 4, MATCH => 8, - CONTROL => 16, - MULTIPORT => 32 - }; + CONTROL => 16 }; -my %optiontype = ( rule => CONTROL, - cmd => CONTROL, +my %special = ( rule => CONTROL, + cmd => CONTROL, - dhcp => UNIQUE, - - mode => CONTROL, - cmdlevel => CONTROL, - simple => CONTROL, - - i => UNIQUE, - s => UNIQUE, - o => UNIQUE, - d => UNIQUE, - p => UNIQUE, - dport => UNIQUE, - sport => UNIQUE, - - 'icmp-type' => MULTIPORT, - 'icmpv6-type' => MULTIPORT, - sports => MULTIPORT, - dports => MULTIPORT, + dhcp => UNIQUE, - comment => CONTROL, + mode => CONTROL, + cmdlevel => CONTROL, + simple => CONTROL, - policy => MATCH, - state => EXCLUSIVE, + i => UNIQUE, + s => UNIQUE, + o => UNIQUE, + d => UNIQUE, + p => UNIQUE, + dport => UNIQUE, + sport => UNIQUE, - jump => TARGET, - target => TARGET, - targetopts => TARGET, - ); + comment => CONTROL, + + policy => MATCH, + state => EXCLUSIVE, + + jump => TARGET, + target => TARGET, + targetopts => TARGET, + ); my %aliases = ( protocol => 'p', source => 's', @@ -489,7 +472,7 @@ my %aliases = ( protocol => 'p', sport => 'sport', ); -my @unique_options = ( qw/p dport sport icmp-type icmpv6-type s d i o/ ); +my @unique_options = ( qw/p dport sport s d i o/ ); # # Rather than initializing globals in an INIT block or during declaration, @@ -632,18 +615,18 @@ sub set_rule_option( $$$ ) { $ruleref->{simple} = 0; - my $optiontype = $optiontype{$option} || MATCH; + my $special = $special{$option} || MATCH; if ( exists $ruleref->{$option} ) { assert( defined $ruleref->{$option} ); - if ( $optiontype == MATCH ) { + if ( $special == MATCH ) { assert( $globals{KLUDGEFREE} ); $ruleref->{$option} = [ $ruleref->{$option} ] unless reftype $ruleref->{$option}; push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value ); - } elsif ( $optiontype == EXCLUSIVE || $optiontype == MULTIPORT ) { + } elsif ( $special == EXCLUSIVE ) { $ruleref->{$option} .= ",$value"; - } elsif ( $optiontype == UNIQUE ) { + } elsif ( $special == UNIQUE ) { fatal_error "Multiple $option settings in one rule is prohibited"; } else { assert(0); @@ -787,18 +770,10 @@ sub format_rule( $$;$ ) { } } - for ( qw/sports dports/ ) { - if ( exists $ruleref->{$_} ) { - my $value = $ruleref->{$_}; - my $invert = ( $value =~ s/^! // ) ? '! ' : ''; - $rule .= "-m multiport ${invert}--$_ $ruleref->{$_}"; - } - } - $rule .= format_option( 'state', $ruleref->{state} ) if defined $ruleref->{state}; $rule .= format_option( 'policy', $ruleref->{policy} ) if defined $ruleref->{policy}; - $rule .= format_option( $_, $ruleref->{$_} ) for sort ( grep ! $optiontype{$_}, keys %{$ruleref} ); + $rule .= format_option( $_, $ruleref->{$_} ) for sort ( grep ! $special{$_}, keys %{$ruleref} ); if ( $ruleref->{target} ) { $rule .= join( ' ', " -$ruleref->{jump}", $ruleref->{target} ); @@ -826,11 +801,7 @@ sub merge_rules( $$$ ) { $toref->{$option} = $fromref->{$option} if exists $fromref->{$option}; } - for my $option ( grep $optiontype{$_} == MULTIPORT, keys %$fromref ) { - set_rule_option( $toref, $option, $fromref->{$option} ); - } - - for my $option ( grep ! $optiontype{$_}, keys %$fromref ) { + for my $option ( grep ! $special{$_}, keys %$fromref ) { set_rule_option( $toref, $option, $fromref->{$option} ); } @@ -990,66 +961,6 @@ sub handle_port_list( $$$$$$ ) { } } -sub handle_iport_list( $$$$ ); - -sub handle_iport_list( $$$$ ) { - my ($chainref, $ruleref, $dports, $ports ) = @_; - - if ( port_count( $ports ) > 15 ) { - # - # More than 15 ports specified - # - my @ports = split '([,:])', $ports; - - while ( @ports ) { - my $count = 0; - my $newports = ''; - - while ( @ports && $count < 15 ) { - my ($port, $separator) = ( shift @ports, shift @ports ); - - $separator ||= ''; - - if ( ++$count == 15 ) { - if ( $separator eq ':' ) { - unshift @ports, $port, ':'; - chop $newports; - last; - } else { - $newports .= $port; - } - } else { - $newports .= "${port}${separator}"; - } - } - - my %newrule = %$ruleref; - - if ( $dports ) { - $newrule{dports} = $newports; - - if ( my $sports = $newrule{sports} ) { - handle_iport_list( $chainref, \%newrule, 0 , $sports ); - } else { - push @{$chainref->{rules}}, \%newrule; - trace( $chainref, 'A', @{$chainref->{rules}}, format_rule( $chainref, \%newrule ) ) if $debug; - } - } else { - $newrule{sports} = $newports; - push @{$chainref->{rules}}, \%newrule; - trace( $chainref, 'A', @{$chainref->{rules}}, format_rule( $chainref, \%newrule ) ) if $debug; - } - } - } elsif ( $dports && ( $ports = $ruleref->{sports} ) ) { - handle_iport_list( $chainref, $ruleref, $ports, 0 ); - } else { - push @{$chainref->{rules}}, $ruleref; - trace( $chainref, 'A', @{$chainref->{rules}}, format_rule( $chainref, $ruleref ) ) if $debug; - } - - 1; -} - # # This much simpler function splits a rule with an icmp type list into discrete rules # @@ -1059,20 +970,6 @@ sub handle_icmptype_list( $$$$ ) { push_rule ( $chainref, join ( '', $first, shift @ports, $rest ) ) while @ports; } -sub handle_icmptype_ilist( $$$$ ) { - my ($chainref, $ruleref, $option, $types ) = @_; - my @types = split ',', $types; - - while ( @types ) { - my %newrule = %$ruleref; - - $newrule{$option} = shift @types; - - push @{$chainref->{rules}}, \%newrule; - trace( $chainref, 'A', @{$chainref->{rules}}, format_rule( $chainref, \%newrule ) ) if $debug; - } -} - # # Add a rule to a chain. Arguments are: # @@ -1149,7 +1046,7 @@ sub push_matches { $dont_optimize; } -sub push_irule( $$$$;@ ) { +sub push_irule( $$$;@ ) { my ( $chainref, $jump, $target, @matches ) = @_; ( $target, my $targetopts ) = split ' ', $target, 2; @@ -1172,36 +1069,8 @@ sub push_irule( $$$$;@ ) { $chainref->{referenced} = 1; - my $expandports; - - if ( @matches ) { - my $first = $matches[0]; - shift @matches if $expandports = ( $first =~ /^\d$/ ); - } else { - $ruleref->{simple} = 1; - } - - $chainref->{dont_optimize} = 1 if push_matches( $ruleref, @matches ); - - if ( $expandports ) { - # - # Caller wants us to split long port lists - # - if ( my $dports = $ruleref->{dports} ) { - return handle_iport_list( $chainref, $ruleref, 1, $dports ); - } - - if ( my $sports = $ruleref->{sports} ) { - return handle_iport_list( $chainref, $ruleref, 0, $sports ); - } - - my $types; - - if ( $types = $ruleref->{'icmp-type'} ) { - return handle_icmp_ilist( $chainref, $ruleref, 'icmp-type', $types ); - } elsif ( $types = $ruleref->{'icmpv6-type'} ) { - return handle_icmp_ilist( $chainref, $ruleref, 'icmpv6-type', $types ); - } + unless ( $ruleref->{simple} = ! @matches ) { + $chainref->{dont_optimize} = 1 if push_matches( $ruleref, @matches ); } push @{$chainref->{rules}}, $ruleref; @@ -3108,178 +2977,6 @@ sub do_proto( $$$;$ ) $output; } -sub do_iproto( $$$;$ ) -{ - my ($proto, $ports, $sports, $restricted ) = @_; - - my @output; - - $proto = '' if $proto eq '-'; - $ports = '' if $ports eq '-'; - $sports = '' if $sports eq '-'; - - if ( $proto ne '' ) { - - my $synonly = ( $proto =~ s/:syn$//i ); - my $invert = ( $proto =~ s/^!// ? '! ' : '' ); - my $protonum = resolve_proto $proto; - - if ( defined $protonum ) { - # - # Protocol is numeric and <= 255 or is defined in /etc/protocols or NSS equivalent - # - fatal_error "'!0' not allowed in the PROTO column" if $invert && ! $protonum; - - my $pname = proto_name( $proto = $protonum ); - # - # $proto now contains the protocol number and $pname contains the canonical name of the protocol - # - unless ( $synonly ) { - @output = ( p => "${invert}${proto}" ); - } else { - fatal_error '":syn" is only allowed with tcp' unless $proto == TCP && ! $invert; - @output = ( p => "${invert}${proto} --syn" ); - } - - fatal_error "SOURCE/DEST PORT(S) not allowed with PROTO !$pname" if $invert && ($ports ne '' || $sports ne ''); - - PROTO: - { - if ( $proto == TCP || $proto == UDP || $proto == SCTP || $proto == DCCP || $proto == UDPLITE ) { - my $multiport = 0; - - if ( $ports ne '' ) { - $invert = $ports =~ s/^!// ? '! ' : ''; - if ( $ports =~ tr/,/,/ > 0 || $sports =~ tr/,/,/ > 0 || $proto == UDPLITE ) { - fatal_error "Port lists require Multiport support in your kernel/iptables" unless have_capability( 'MULTIPORT' ); - fatal_error "Multiple ports not supported with SCTP" if $proto == SCTP; - - if ( port_count ( $ports ) > 15 ) { - if ( $restricted ) { - fatal_error "A port list in this file may only have up to 15 ports"; - } elsif ( $invert ) { - fatal_error "An inverted port list may only have up to 15 ports"; - } - } - - $ports = validate_port_list $pname , $ports; - push @output, dports => "${invert} $ports"; - $multiport = 1; - } else { - fatal_error "Missing DEST PORT" unless supplied $ports; - $ports = validate_portpair $pname , $ports; - push @output, dport => "${invert}$(ports}"; - } - } else { - $multiport = ( ( $sports =~ tr/,/,/ ) > 0 || $proto == UDPLITE ); - } - - if ( $sports ne '' ) { - $invert = $sports =~ s/^!// ? '! ' : ''; - if ( $multiport ) { - - if ( port_count( $sports ) > 15 ) { - if ( $restricted ) { - fatal_error "A port list in this file may only have up to 15 ports"; - } elsif ( $invert ) { - fatal_error "An inverted port list may only have up to 15 ports"; - } - } - - $sports = validate_port_list $pname , $sports; - push @output, sports => "${invert} $sports"; - } else { - fatal_error "Missing SOURCE PORT" unless supplied $sports; - $sports = validate_portpair $pname , $sports; - push @output, dport => "${invert}$(ports}"; - } - } - - last PROTO; } - - if ( $proto == ICMP ) { - fatal_error "ICMP not permitted in an IPv6 configuration" if $family == F_IPV6; #User specified proto 1 rather than 'icmp' - if ( $ports ne '' ) { - $invert = $ports =~ s/^!// ? '! ' : ''; - - my $types; - - if ( $ports =~ /,/ ) { - fatal_error "An inverted ICMP list may only contain a single type" if $invert; - $types = ''; - for my $type ( split_list( $ports, 'ICMP type list' ) ) { - $types = $types ? join( ',', $types, validate_icmp( $type ) ) : $type; - } - } else { - $types = validate_icmp $ports; - } - - push @output, 'icmp-type' => "${invert}${types}"; - } - - fatal_error 'SOURCE PORT(S) not permitted with ICMP' if $sports ne ''; - - last PROTO; } - - if ( $proto == IPv6_ICMP ) { - fatal_error "IPv6_ICMP not permitted in an IPv4 configuration" if $family == F_IPV4; - if ( $ports ne '' ) { - $invert = $ports =~ s/^!// ? '! ' : ''; - - my $types; - - if ( $ports =~ /,/ ) { - fatal_error "An inverted ICMP list may only contain a single type" if $invert; - $types = ''; - for my $type ( list_split( $ports, 'ICMP type list' ) ) { - $types = $types ? join( ',', $types, validate_icmp6( $type ) ) : $type; - } - } else { - $types = validate_icmp6 $ports; - } - - push @output, 'icmpv6-type' => "${invert}${types}"; - } - - fatal_error 'SOURCE PORT(S) not permitted with IPv6-ICMP' if $sports ne ''; - - last PROTO; } - - - fatal_error "SOURCE/DEST PORT(S) not allowed with PROTO $pname" if $ports ne '' || $sports ne ''; - - } # PROTO - - } else { - fatal_error '":syn" is only allowed with tcp' if $synonly; - - if ( $proto =~ /^(ipp2p(:(tcp|udp|all))?)$/i ) { - my $p = $2 ? lc $3 : 'tcp'; - require_capability( 'IPP2P_MATCH' , "PROTO = $proto" , 's' ); - $proto = '-p ' . proto_name($p) . ' '; - - my $options = ''; - - if ( $ports ne 'ipp2p' ) { - $options .= " --$_" for split /,/, $ports; - } - - $options = have_capability( 'OLD_IPP2P_MATCH' ) ? '--ipp2p' : '--edk --kazaa --gnu --dc' unless $options; - - @output = ( p => ${proto}, ipp2p => ${options} ) - } else { - fatal_error "Invalid/Unknown protocol ($proto)" - } - } - } else { - # - # No protocol - # - fatal_error "SOURCE/DEST PORT(S) not allowed without PROTO" if $ports ne '' || $sports ne ''; - } - - \@output; -} sub do_mac( $ ) { my $mac = $_[0]; @@ -3302,7 +2999,7 @@ sub do_imac( $ ) { fatal_error "Invalid MAC address ($mac)" unless $mac =~ /^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/; - [ mac => "${invert}--mac-source $mac" ]; + ( mac => "${invert}--mac-source $mac" ); } # @@ -3369,28 +3066,6 @@ sub do_test ( $$ ) "$match $testval "; } -sub do_itest ( $$ ) -{ - my ($testval, $mask) = @_; - - my $originaltestval = $testval; - - return [] unless defined $testval and $testval ne '-'; - - $mask = '' unless defined $mask; - - my $invert = $testval =~ s/^!// ? '! ' : ''; - my $match = $testval =~ s/:C$// ? 'connmark' : 'mark'; - - fatal_error "Invalid MARK value ($originaltestval)" if $testval eq '/'; - - validate_mark $testval; - - $testval = join( '/', $testval, in_hex($mask) ) unless ( $testval =~ '/' ); - - [ $match => "--mark $testval" ]; -} - my %norate = ( DROP => 1, REJECT => 1 ); # @@ -3455,71 +3130,6 @@ sub do_ratelimit( $$ ) { } } -sub do_iratelimit( $$ ) { - my ( $rate, $action ) = @_; - - return [] unless $rate and $rate ne '-'; - - fatal_error "Rate Limiting not available with $action" if $norate{$action}; - # - # "-m hashlimit" match for the passed LIMIT/BURST - # - if ( $rate =~ /^[sd]:{1,2}/ ) { - require_capability 'HASHLIMIT_MATCH', 'Per-ip rate limiting' , 's'; - - my $limit = ''; - my $match = have_capability( 'OLD_HL_MATCH' ) ? 'hashlimit' : 'hashlimit-upto'; - my $units; - - if ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) { - fatal_error "Invalid Rate ($3)" unless $4; - fatal_error "Invalid Burst ($7)" unless $7; - $limit .= "--hashlimit $3 --hashlimit-burst $7 --hashlimit-name "; - $limit .= $2 ? $2 : 'shorewall' . $hashlimitset++; - $limit .= ' --hashlimit-mode '; - $units = $6; - } elsif ( $rate =~ /^[sd]:((\w*):)?((\d+)(\/(sec|min|hour|day))?)$/ ) { - fatal_error "Invalid Rate ($3)" unless $4; - $limit .= "--$match $3 --hashlimit-name "; - $limit .= $2 ? $2 : 'shorewall' . $hashlimitset++; - $limit .= ' --hashlimit-mode '; - $units = $6; - } else { - fatal_error "Invalid rate ($rate)"; - } - - $limit .= $rate =~ /^s:/ ? 'srcip ' : 'dstip '; - - if ( $units && $units ne 'sec' ) { - my $expire = 60000; # 1 minute in milliseconds - - if ( $units ne 'min' ) { - $expire *= 60; #At least an hour - $expire *= 24 if $units eq 'day'; - } - - $limit .= "--hashlimit-htable-expire $expire "; - } - - return [ $match => $limit ]; - } - - if ( $rate =~ /^((\d+)(\/(sec|min|hour|day))?):(\d+)$/ ) { - fatal_error "Invalid Rate ($1)" unless $2; - fatal_error "Invalid Burst ($5)" unless $5; - - return [ limit => "--limit $1 --limit-burst $5" ]; - } - - if ( $rate =~ /^(\d+)(\/(sec|min|hour|day))?$/ ) { - fatal_error "Invalid Rate (${1}${2})" unless $1; - - return [ limit => "--limit $rate" ]; - } - - fatal_error "Invalid rate ($rate)"; -} - # # Create a "-m connlimit" match for the passed CONNLIMIT # @@ -3542,27 +3152,6 @@ sub do_connlimit( $ ) { } } -sub do_iconnlimit( $ ) { - my ( $limit ) = @_; - - return [] if $limit eq '-'; - - require_capability 'CONNLIMIT_MATCH', 'A non-empty CONNLIMIT', 's'; - - my $invert = $limit =~ s/^!// ? '' : '! '; # Note Carefully -- we actually do 'connlimit-at-or-below' - - if ( $limit =~ /^(\d+):(\d+)$/ ) { - fatal_error "Invalid Mask ($2)" unless $2 > 0 || $2 < 31; - return [ connlimit => "${invert}--connlimit-above $1 --connlimit-mask $2" ]; - } - - if ( $limit =~ /^(\d+)$/ ) { - return [ connlimit => "${invert}--connlimit-above $limit" ]; - } - - fatal_error "Invalid connlimit ($limit)"; -} - sub do_time( $ ) { my ( $time ) = @_; @@ -3600,43 +3189,6 @@ sub do_time( $ ) { $result; } -sub do_iime( $ ) { - my ( $time ) = @_; - - return [] if $time eq '-'; - - require_capability 'TIME_MATCH', 'A non-empty TIME', 's'; - - my $result = ''; - - for my $element (split /&/, $time ) { - fatal_error "Invalid time element list ($time)" unless defined $element && $element; - - if ( $element =~ /^(timestart|timestop)=(\d{1,2}:\d{1,2}(:\d{1,2})?)$/ ) { - $result .= "--$1 $2 "; - } elsif ( $element =~ /^weekdays=(.*)$/ ) { - my $days = $1; - for my $day ( split /,/, $days ) { - fatal_error "Invalid weekday ($day)" unless $day =~ /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)$/ || ( $day =~ /^\d$/ && $day && $day <= 7); - } - $result .= "--weekday $days "; - } elsif ( $element =~ /^monthdays=(.*)$/ ) { - my $days = $1; - for my $day ( split /,/, $days ) { - fatal_error "Invalid day of the month ($day)" unless $day =~ /^\d{1,2}$/ && $day && $day <= 31; - } - } elsif ( $element =~ /^(datestart|datestop)=(\d{4}(-\d{2}(-\d{2}(T\d{1,2}(:\d{1,2}){0,2})?)?)?)$/ ) { - $result .= "--$1 $2 "; - } elsif ( $element =~ /^(utc|localtz)$/ ) { - $result .= "--$1 "; - } else { - fatal_error "Invalid time element ($element)"; - } - } - - [ time => $result ]; -} - # # Create a "-m owner" match for the passed USER/GROUP # @@ -3681,47 +3233,6 @@ sub do_user( $ ) { $rule; } -sub do_iuser( $ ) { - my $user = $_[0]; - my $rule = ''; - - return [] unless defined $user and $user ne '-'; - - if ( $user =~ /^(!)?(.*)\+(.*)$/ ) { - $rule .= "! --cmd-owner $2 " if supplied $2; - $user = "!$1"; - } elsif ( $user =~ /^(.*)\+(.*)$/ ) { - $rule .= "--cmd-owner $2 " if supplied $2; - $user = $1; - } - - if ( $user =~ /^(!)?(.*):(.*)$/ ) { - my $invert = $1 ? '! ' : ''; - my $group = defined $3 ? $3 : ''; - if ( supplied $2 ) { - $user = $2; - fatal_error "Unknown user ($user)" unless $user =~ /^\d+$/ || $globals{EXPORT} || defined getpwnam( $user ); - $rule .= "${invert}--uid-owner $user "; - } - - if ( $group ne '' ) { - fatal_error "Unknown group ($group)" unless $group =~ /\d+$/ || $globals{EXPORT} || defined getgrnam( $group ); - $rule .= "${invert}--gid-owner $group "; - } - } elsif ( $user =~ /^(!)?(.*)$/ ) { - my $invert = $1 ? '! ' : ''; - $user = $2; - fatal_error "Invalid USER/GROUP (!)" if $user eq ''; - fatal_error "Unknown user ($user)" unless $user =~ /^\d+$/ || $globals{EXPORT} || defined getpwnam( $user ); - $rule .= "${invert}--uid-owner $user "; - } else { - fatal_error "Unknown user ($user)" unless $user =~ /^\d+$/ || $globals{EXPORT} || defined getpwnam( $user ); - $rule .= "--uid-owner $user "; - } - - [ owner => $rule ]; -} - # # Create a "-m tos" match for the passed TOS # @@ -3731,12 +3242,6 @@ sub do_tos( $ ) { $tos ne '-' ? "-m tos --tos $tos " : ''; } -sub do_itos( $ ) { - my $tos = $_[0]; - - $tos ne '-' ? [ tos => "--tos $tos" ] : []; -} - my %dir = ( O => 'original' , R => 'reply' , B => 'both' ); @@ -3767,25 +3272,6 @@ sub do_connbytes( $ ) { "-m connbytes ${invert}--connbytes $min:$max --connbytes-dir $dir{$dir} --connbytes-mode $mode{$mode} "; } -sub do_iconnbytes( $ ) { - my $connbytes = $_[0]; - - return [] if $connbytes eq '-'; - # 1 2 3 5 6 - fatal_error "Invalid CONNBYTES ($connbytes)" unless $connbytes =~ /^(!)? (\d+): (\d+)? ((:[ORB]) (:[PBA])?)?$/x; - - my $invert = $1 || ''; $invert = '! ' if $invert; - my $min = $2; $min = 0 unless defined $min; - my $max = $3; $max = '' unless defined $max; fatal_error "Invalid byte range ($min:$max)" if $max ne '' and $min > $max; - my $dir = $5 || 'B'; - my $mode = $6 || 'B'; - - $dir =~ s/://; - $mode =~ s/://; - - [ connbytes => "${invert}--connbytes $min:$max --connbytes-dir $dir{$dir} --connbytes-mode $mode{$mode}" ]; -} - # # Create a soft "-m helper" match for the passed argument # @@ -3797,14 +3283,6 @@ sub do_helper( $ ) { qq(-m helper --helper "$helper" ); } -sub do_ihelper( $ ) { - my $helper = shift; - - return [] if $helper eq '-'; - - [ helper => qq(--helper "$helper") ]; -} - # # Create a "-m length" match for the passed LENGTH # @@ -3815,13 +3293,6 @@ sub do_length( $ ) { $length ne '-' ? "-m length --length $length " : ''; } -sub do_ilength( $ ) { - my $length = $_[0]; - - require_capability( 'LENGTH_MATCH' , 'A Non-empty LENGTH' , 's' ); - $length ne '-' ? [ length > "--length $length" ] : []; -} - # # Create a "-m -ipv6header" match for the passed argument # @@ -3873,35 +3344,7 @@ sub do_headers( $ ) { } } - "-m ipv6header ${invert}--header ${headers} ${soft} "; -} - -sub do_iheaders( $ ) { - my $headers = shift; - - return [] if $headers eq '-'; - - require_capability 'HEADER_MATCH', 'A non-empty HEADER column', 's'; - - my $invert = $headers =~ s/^!// ? '! ' : ""; - - my $soft = '--soft '; - - if ( $headers =~ s/^exactly:// ) { - $soft = ''; - } else { - $headers =~ s/^any://; - } - - for ( split_list $headers, "Header" ) { - if ( $_ eq 'proto' ) { - $_ = 'protocol'; - } else { - fatal_error "Unknown IPv6 Header ($_)" unless $headers{$_}; - } - } - - [ ipv6header => "${invert}--header ${headers} ${soft}" ]; + "-m ipv6header ${invert}--header ${headers} ${soft}"; } # @@ -4172,7 +3615,7 @@ sub imatch_source_net( $;$\$ ) { if ( $net =~ /^!?~/ ) { fatal_error "A MAC address($net) cannot be used in this context" if $restriction >= OUTPUT_RESTRICT; $$macref = 1 if $macref; - return @{do_imac $net}; + return do_imac $net; } if ( $net =~ /^(!?)\+(6_)?[a-zA-Z][-\w]*(\[.*\])?/ ) { diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 701e5c933..74b0ff78f 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -3406,12 +3406,12 @@ sub get_configuration( $$$ ) { $globals{STATEMATCH} = '-m conntrack --ctstate' if have_capability 'CONNTRACK_MATCH'; if ( my $rate = $config{LOGLIMIT} ) { - my $limit; + my ( $option, $limit ); if ( $rate =~ /^[sd]:/ ) { require_capability 'HASHLIMIT_MATCH', 'Per-ip log rate limiting' , 's'; - $limit = "-m hashlimit "; + $option = 'hashlimit'; my $match = have_capability( 'OLD_HL_MATCH' ) ? 'hashlimit' : 'hashlimit-upto'; my $units; @@ -3420,11 +3420,11 @@ sub get_configuration( $$$ ) { fatal_error "Invalid rate ($1)" unless $2; fatal_error "Invalid burst value ($5)" unless $5; - $limit .= "--$match $1 --hashlimit-burst $5 --hashlimit-name lograte --hashlimit-mode "; + $limit = "--$match $1 --hashlimit-burst $5 --hashlimit-name lograte --hashlimit-mode "; $units = $4; } elsif ( $rate =~ /^[sd]:((\d+)(\/(sec|min|hour|day))?)$/ ) { fatal_error "Invalid rate ($1)" unless $2; - $limit .= "--$match $1 --hashlimit-name lograte --hashlimit-mode "; + $limit = "--$match $1 --hashlimit-name lograte --hashlimit-mode "; $units = $4; } else { fatal_error "Invalid rate ($rate)"; @@ -3442,18 +3442,22 @@ sub get_configuration( $$$ ) { $limit .= "--hashlimit-htable-expire $expire "; } - } elsif ( $rate =~ /^((\d+)(\/(sec|min|hour|day))):(\d+)$/ ) { - fatal_error "Invalid rate ($1)" unless $2; - fatal_error "Invalid burst value ($5)" unless $5; - $limit = "-m limit --limit $1 --limit-burst $5 "; - } elsif ( $rate =~ /^(\d+)(\/(sec|min|hour|day))?$/ ) { - fatal_error "Invalid rate (${1}${2})" unless $1; - $limit = "-m limit --limit $rate "; } else { - fatal_error "Invalid rate ($rate)"; + $option = 'limit'; + + if ( $rate =~ /^((\d+)(\/(sec|min|hour|day))):(\d+)$/ ) { + fatal_error "Invalid rate ($1)" unless $2; + fatal_error "Invalid burst value ($5)" unless $5; + $limit = "--limit $1 --limit-burst $5"; + } elsif ( $rate =~ /^(\d+)(\/(sec|min|hour|day))?$/ ) { + fatal_error "Invalid rate (${1}${2})" unless $1; + $limit = "--limit $rate"; + } else { + fatal_error "Invalid rate ($rate)"; + } } - $globals{LOGLIMIT} = $limit; + $globals{LOGLIMIT} = [ $option => $limit ]; warning_message "LOGRATE Ignored when LOGLIMIT is specified" if $config{LOGRATE}; warning_message "LOGBURST Ignored when LOGLIMIT is specified" if $config{LOGBURST}; @@ -3467,11 +3471,12 @@ sub get_configuration( $$$ ) { fatal_error"Invalid LOGBURST ($config{LOGBURST})" unless $config{LOGBURST} =~ /^\d+$/; } - $globals{LOGLIMIT} = '-m limit '; - $globals{LOGLIMIT} .= "--limit $config{LOGRATE} " if supplied $config{LOGRATE}; - $globals{LOGLIMIT} .= "--limit-burst $config{LOGBURST} " if supplied $config{LOGBURST}; + my $limit = "--limit $config{LOGRATE} " if supplied $config{LOGRATE}; + $limit .= "--limit-burst $config{LOGBURST} " if supplied $config{LOGBURST}; + + $globals{LOGLIMIT} = [ limit => $limit ]; } else { - $globals{LOGLIMIT} = ''; + $globals{LOGLIMIT} = []; } check_trivalue ( 'IP_FORWARDING', 'on' );