mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-08 16:54:10 +01:00
First cut at pinning local clients to providers
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@9525 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
04ff1fb5e0
commit
99deb41bbc
@ -72,6 +72,7 @@ our %EXPORT_TAGS = (
|
||||
add_command
|
||||
add_commands
|
||||
move_rules
|
||||
purge_rules
|
||||
insert_rule1
|
||||
add_tunnel_rule
|
||||
process_comment
|
||||
@ -665,6 +666,17 @@ sub move_rules( $$ ) {
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Purge the rules from the passed chain are return them
|
||||
#
|
||||
sub purge_rules( $ ) {
|
||||
my $chainref = shift;
|
||||
my @rules = @{$chainref->{rules}};
|
||||
$chainref->{rules} = [];
|
||||
$chainref->{referenced} = 0;
|
||||
@rules;
|
||||
}
|
||||
|
||||
#
|
||||
# Change the passed interface name so it is a legal shell variable name.
|
||||
#
|
||||
|
@ -33,7 +33,7 @@ use Shorewall::Chains qw(:DEFAULT :internal);
|
||||
use strict;
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw( setup_providers @routemarked_interfaces);
|
||||
our @EXPORT = qw( setup_providers @routemarked_interfaces handle_stickiness );
|
||||
our @EXPORT_OK = qw( initialize lookup_provider );
|
||||
our $VERSION = 4.2.4;
|
||||
|
||||
@ -101,18 +101,21 @@ sub setup_route_marking() {
|
||||
add_rule $mangle_table->{PREROUTING} , "-m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask";
|
||||
add_rule $mangle_table->{OUTPUT} , "-m connmark ! --mark 0/$mask -j CONNMARK --restore-mark --mask $mask";
|
||||
|
||||
my $chainref = new_chain 'mangle', 'routemark';
|
||||
my $chainref = new_chain 'mangle', 'routemark';
|
||||
my $chainref1 = new_chain 'mangle', 'stickymark';
|
||||
|
||||
my %marked_interfaces;
|
||||
|
||||
for my $providerref ( @routemarked_providers ) {
|
||||
my $interface = $providerref->{interface};
|
||||
my $mark = $providerref->{mark};
|
||||
my $base = uc chain_base $interface;
|
||||
|
||||
add_command( $chainref, qq(if [ -n "\$${base}_IS_UP" ]; then) ), incr_cmd_level( $chainref ) if $providerref->{optional};
|
||||
|
||||
unless ( $marked_interfaces{$interface} ) {
|
||||
add_rule $mangle_table->{PREROUTING} , "-i $interface -m mark --mark 0/$mask -j routemark";
|
||||
add_jump $mangle_table->{PREROUTING} , $chainref1, 0, "-i ! $interface -m mark --mark $mark/$mask ";
|
||||
$marked_interfaces{$interface} = 1;
|
||||
}
|
||||
|
||||
@ -754,4 +757,50 @@ sub lookup_provider( $ ) {
|
||||
$providerref->{shared} ? $providerref->{number} : 0;
|
||||
}
|
||||
|
||||
#
|
||||
# The Tc module has collected the 'sticky' rules in the 'sticky' chain. In this function, we apply them
|
||||
# to the 'tracked' providers
|
||||
#
|
||||
sub handle_stickiness() {
|
||||
my $stickyref = $mangle_table->{sticky};
|
||||
my $stickymarkref = $mangle_table->{stickymark};
|
||||
my $tcpreref = $mangle_table->{tcpre};
|
||||
my @rules = purge_rules $stickyref;
|
||||
my %marked_interfaces;
|
||||
my $sticky = 1;
|
||||
|
||||
fatal_error "There are STICKY tcrules but no 'track' providers" unless @routemarked_providers;
|
||||
|
||||
for my $providerref ( @routemarked_providers ) {
|
||||
my $interface = $providerref->{interface};
|
||||
my $base = uc chain_base $interface;
|
||||
my $mark = $providerref->{mark};
|
||||
|
||||
for my $rule ( @rules ) {
|
||||
my $rule1;
|
||||
my $list = sprintf "sticky%03d" , $sticky++;
|
||||
|
||||
$rule =~ s/-A //;
|
||||
|
||||
for my $chainref ( $tcpreref, $stickymarkref ) {
|
||||
|
||||
add_command( $chainref, qq(if [ -n "\$${base}_IS_UP" ]; then) ), incr_cmd_level( $chainref ) if $providerref->{optional};
|
||||
|
||||
if ( $chainref->{name} eq 'tcpre' ) {
|
||||
$rule1 = $rule;
|
||||
$rule1 =~ s/-j RETURN/-m recent --name $list --update --seconds 120 -j MARK --set-mark $mark/;
|
||||
} else {
|
||||
$rule1 = $rule;
|
||||
$rule1 =~ s/-j RETURN/-m mark --mark $mark -m recent --name $list --set/;
|
||||
}
|
||||
|
||||
add_rule $chainref, $rule1;
|
||||
|
||||
decr_cmd_level( $chainref), add_command( $chainref, "fi" ) if $providerref->{optional};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -97,6 +97,12 @@ our @tccmd = ( { match => sub ( $ ) { $_[0] eq 'SAVE' } ,
|
||||
mask => '' ,
|
||||
connmark => 0
|
||||
} ,
|
||||
{ match => sub ( $ ) { $_[0] eq 'SAME' },
|
||||
target => 'sticky' ,
|
||||
mark => NOMARK ,
|
||||
mask => '' ,
|
||||
connmark => 0
|
||||
} ,
|
||||
{ match => sub ( $ ) { $_[0] =~ '\|.*'} ,
|
||||
target => 'MARK --or-mark' ,
|
||||
mark => HIGHMARK ,
|
||||
@ -149,6 +155,7 @@ our @tcdevices;
|
||||
our %tcdevices;
|
||||
our @devnums;
|
||||
our $devnum;
|
||||
our $sticky;
|
||||
|
||||
|
||||
#
|
||||
@ -171,7 +178,8 @@ our %tcclasses;
|
||||
our %restrictions = ( tcpre => PREROUTE_RESTRICT ,
|
||||
tcpost => POSTROUTE_RESTRICT ,
|
||||
tcfor => NO_RESTRICT ,
|
||||
tcout => OUTPUT_RESTRICT );
|
||||
tcout => OUTPUT_RESTRICT ,
|
||||
sticky => PREROUTE_RESTRICT );
|
||||
|
||||
our $family;
|
||||
|
||||
@ -194,6 +202,7 @@ sub initialize( $ ) {
|
||||
%tcclasses = ();
|
||||
@devnums = ();
|
||||
$devnum = 0;
|
||||
$sticky = 0;
|
||||
}
|
||||
|
||||
INIT {
|
||||
@ -214,6 +223,7 @@ sub process_tc_rule( $$$$$$$$$$$$ ) {
|
||||
my $classid = 0;
|
||||
my $device = '';
|
||||
my $fw = firewall_zone;
|
||||
my $list;
|
||||
|
||||
if ( $source ) {
|
||||
if ( $source eq $fw ) {
|
||||
@ -256,6 +266,8 @@ sub process_tc_rule( $$$$$$$$$$$$ ) {
|
||||
|
||||
my ($cmd, $rest) = split( '/', $mark, 2 );
|
||||
|
||||
$list = '';
|
||||
|
||||
unless ( $classid ) {
|
||||
MARK:
|
||||
{
|
||||
@ -274,6 +286,11 @@ sub process_tc_rule( $$$$$$$$$$$$ ) {
|
||||
$mark =~ s/^[|&]//;
|
||||
}
|
||||
|
||||
if ( $target eq 'sticky ' ) {
|
||||
$target = 'RETURN';
|
||||
$chain = 'sticky';
|
||||
}
|
||||
|
||||
if ( $rest ) {
|
||||
fatal_error "Invalid MARK ($originalmark)" if $marktype == NOMARK;
|
||||
|
||||
@ -904,6 +921,7 @@ sub setup_tc() {
|
||||
if ( $capabilities{MANGLE_ENABLED} && $config{MANGLE_ENABLED} ) {
|
||||
ensure_mangle_chain 'tcpre';
|
||||
ensure_mangle_chain 'tcout';
|
||||
new_chain 'mangle', 'sticky';
|
||||
|
||||
if ( $capabilities{MANGLE_FORWARD} ) {
|
||||
ensure_mangle_chain 'tcfor';
|
||||
@ -966,6 +984,10 @@ sub setup_tc() {
|
||||
for ( @deferred_rules ) {
|
||||
add_rule ensure_chain( 'mangle' , 'tcpost' ), $_;
|
||||
}
|
||||
|
||||
if ( $mangle_table->{sticky}{referenced} ) {
|
||||
handle_stickiness;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -735,14 +735,14 @@ sub validate_interfaces_file( $ )
|
||||
}
|
||||
}
|
||||
|
||||
my $optionsref = {};
|
||||
my $hostoptionsref = {};
|
||||
|
||||
my %options;
|
||||
my %hostoptions;
|
||||
|
||||
my $hostoptionsref = {};
|
||||
|
||||
if ( $options ) {
|
||||
|
||||
my %hostoptions;
|
||||
|
||||
for my $option (split_list1 $options, 'option' ) {
|
||||
next if $option eq '-';
|
||||
|
||||
@ -817,20 +817,20 @@ sub validate_interfaces_file( $ )
|
||||
require_capability( 'PHYSDEV_MATCH', 'The "bridge" option', 's');
|
||||
fatal_error "Bridges may not have wildcard names" if $wildcard;
|
||||
}
|
||||
|
||||
$hostoptionsref = \%hostoptions;
|
||||
|
||||
} elsif ( $port ) {
|
||||
$options{port} = 1;
|
||||
}
|
||||
|
||||
$optionsref = \%options;
|
||||
$hostoptionsref = \%hostoptions;
|
||||
|
||||
$interfaces{$interface} = { name => $interface ,
|
||||
bridge => $bridge ,
|
||||
nets => 0 ,
|
||||
number => ++$num ,
|
||||
root => $root ,
|
||||
broadcasts => $broadcasts ,
|
||||
options => $optionsref };
|
||||
options => \%options };
|
||||
|
||||
push @ifaces, $interface;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user