mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-23 16:13:18 +01:00
'shared' providers -- phase I
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@7669 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
4db0dc2667
commit
e9d2f2f915
@ -187,6 +187,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT',
|
||||
TCPMSS_MATCH => 'TCPMSS Match',
|
||||
HASHLIMIT_MATCH => 'Hashlimit Match',
|
||||
NFQUEUE_TARGET => 'NFQUEUE Target',
|
||||
REALM_MATCH => 'Realm Match',
|
||||
CAPVERSION => 'Capability Version',
|
||||
);
|
||||
#
|
||||
@ -244,7 +245,7 @@ sub initialize() {
|
||||
LOGPARMS => '',
|
||||
TC_SCRIPT => '',
|
||||
VERSION => '4.0.6',
|
||||
CAPVERSION => 40006 ,
|
||||
CAPVERSION => 40007 ,
|
||||
);
|
||||
#
|
||||
# From shorewall.conf file
|
||||
@ -381,6 +382,7 @@ sub initialize() {
|
||||
TCPMSS_MATCH => undef,
|
||||
HASHLIMIT_MATCH => undef,
|
||||
NFQUEUE_TARGET => undef,
|
||||
REALM_MATCH => undef,
|
||||
CAPVERSION => undef,
|
||||
);
|
||||
#
|
||||
@ -1414,6 +1416,8 @@ sub determine_capabilities( $ ) {
|
||||
$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" );
|
||||
|
||||
$capabilities{REALM_MATCH} = qt( "$iptables -A $sillyname -m realm --realm 1" );
|
||||
|
||||
qt( "$iptables -F $sillyname" );
|
||||
qt( "$iptables -X $sillyname" );
|
||||
|
||||
|
@ -43,6 +43,7 @@ use constant { LOCAL_NUMBER => 255,
|
||||
UNSPEC_NUMBER => 0
|
||||
};
|
||||
|
||||
our @routemarked_providers;
|
||||
our %routemarked_interfaces;
|
||||
our @routemarked_interfaces;
|
||||
|
||||
@ -53,6 +54,8 @@ our %providers;
|
||||
|
||||
our @providers;
|
||||
|
||||
our $maccount;
|
||||
|
||||
#
|
||||
# Initialize globals -- we take this novel approach to globals initialization to allow
|
||||
# the compiler to run multiple times in the same process. The
|
||||
@ -63,9 +66,11 @@ our @providers;
|
||||
#
|
||||
|
||||
sub initialize() {
|
||||
@routemarked_providers = ();
|
||||
%routemarked_interfaces = ();
|
||||
@routemarked_interfaces = ();
|
||||
$balance = 0;
|
||||
$maccount = 0;
|
||||
$first_default_route = 1;
|
||||
|
||||
%providers = ( 'local' => { number => LOCAL_NUMBER , mark => 0 , optional => 0 } ,
|
||||
@ -93,31 +98,46 @@ sub setup_route_marking() {
|
||||
|
||||
my $chainref = new_chain 'mangle', 'routemark';
|
||||
|
||||
while ( my ( $interface, $mark ) = ( each %routemarked_interfaces ) ) {
|
||||
add_rule $mangle_table->{PREROUTING} , "-i $interface -m mark --mark 0/$mask -j routemark";
|
||||
add_rule $chainref, " -i $interface -j MARK --set-mark $mark";
|
||||
my %marked_interfaces;
|
||||
|
||||
for my $providerref ( @routemarked_providers ) {
|
||||
my $interface = $providerref->{interface};
|
||||
|
||||
unless ( $marked_interfaces{$interface} ) {
|
||||
add_rule $mangle_table->{PREROUTING} , "-i $interface -m mark --mark 0/$mask -j routemark";
|
||||
$marked_interfaces{$interface} = 1;
|
||||
}
|
||||
|
||||
if ( $providerref->{shared} ) {
|
||||
my $provider = $providerref->{provider};
|
||||
add_command( $chainref, qq(if [ -n "${provider}_is_up" ]; then) ), incr_cmd_level( $chainref ) if $providerref->{optional};
|
||||
add_rule $chainref, " -m mac --mac-source $providerref->{mac} -j MARK --set-mark $providerref->{mark}";
|
||||
decr_cmd_level( $chainref), add_command( $chainref, "fi" ) if $providerref->{optional};
|
||||
} else {
|
||||
add_rule $chainref, " -i $interface -j MARK --set-mark $providerref->{mark}";
|
||||
}
|
||||
}
|
||||
|
||||
add_rule $chainref, "-m mark ! --mark 0/$mask -j CONNMARK --save-mark --mask $mask";
|
||||
}
|
||||
|
||||
sub copy_table( $$ ) {
|
||||
my ( $duplicate, $number ) = @_;
|
||||
sub copy_table( $$$ ) {
|
||||
my ( $duplicate, $number, $realm ) = @_;
|
||||
|
||||
emit ( "ip route show table $duplicate | while read net route; do",
|
||||
' case $net in',
|
||||
' default|nexthop)',
|
||||
' ;;',
|
||||
' *)',
|
||||
" run_ip route add table $number \$net \$route",
|
||||
" run_ip route add table $number \$net \$route $realm",
|
||||
' ;;',
|
||||
' esac',
|
||||
"done\n"
|
||||
);
|
||||
}
|
||||
|
||||
sub copy_and_edit_table( $$$ ) {
|
||||
my ( $duplicate, $number, $copy ) = @_;
|
||||
sub copy_and_edit_table( $$$$ ) {
|
||||
my ( $duplicate, $number, $copy, $realm) = @_;
|
||||
|
||||
emit ( "ip route show table $duplicate | while read net route; do",
|
||||
' case $net in',
|
||||
@ -126,7 +146,7 @@ sub copy_and_edit_table( $$$ ) {
|
||||
' *)',
|
||||
' case $(find_device $route) in',
|
||||
" $copy)",
|
||||
" run_ip route add table $number \$net \$route",
|
||||
" run_ip route add table $number \$net \$route $realm",
|
||||
' ;;',
|
||||
' esac',
|
||||
' ;;',
|
||||
@ -181,37 +201,18 @@ sub add_a_provider( $$$$$$$$ ) {
|
||||
emit "qt ip route flush table $number";
|
||||
emit "echo \"qt ip route flush table $number\" >> \${VARDIR}/undo_routing";
|
||||
|
||||
if ( $duplicate ne '-' ) {
|
||||
if ( $copy eq '-' ) {
|
||||
copy_table ( $duplicate, $number );
|
||||
} else {
|
||||
if ( $copy eq 'none' ) {
|
||||
$copy = $interface;
|
||||
} else {
|
||||
$copy =~ tr/,/|/;
|
||||
}
|
||||
|
||||
copy_and_edit_table( $duplicate, $number ,$copy );
|
||||
}
|
||||
} else {
|
||||
fatal_error 'A non-empty COPY column requires that a routing table be specified in the DUPLICATE column' if $copy ne '-';
|
||||
}
|
||||
my $variable;
|
||||
|
||||
if ( $gateway eq 'detect' ) {
|
||||
my $variable = get_interface_address $interface;
|
||||
$variable = get_interface_address $interface;
|
||||
emit ( "gateway=\$(detect_gateway $interface)\n",
|
||||
'if [ -n "$gateway" ]; then',
|
||||
" run_ip route replace $variable dev $interface table $number",
|
||||
" run_ip route add default via \$gateway dev $interface table $number",
|
||||
'else',
|
||||
'if [ -z "$gateway" ]; then',
|
||||
" fatal_error \"Unable to detect the gateway through interface $interface\"",
|
||||
"fi\n" );
|
||||
$gateway = '$gateway';
|
||||
} elsif ( $gateway && $gateway ne '-' ) {
|
||||
validate_address $gateway, 0;
|
||||
my $variable = get_interface_address $interface;
|
||||
emit "run_ip route replace $gateway src $variable dev $interface table $number";
|
||||
emit "run_ip route add default via $gateway dev $interface table $number";
|
||||
$variable = get_interface_address $interface;
|
||||
} else {
|
||||
$gateway = '';
|
||||
emit "run_ip route add default dev $interface table $number";
|
||||
@ -244,15 +245,12 @@ sub add_a_provider( $$$$$$$$ ) {
|
||||
);
|
||||
}
|
||||
|
||||
my ( $loose, $optional ) = (0,0);
|
||||
my ( $loose, $optional, $track, $shared ) = (0,0,0,0);
|
||||
|
||||
unless ( $options eq '-' ) {
|
||||
for my $option ( split /,/, $options ) {
|
||||
if ( $option eq 'track' ) {
|
||||
fatal_error "Interface $interface is tracked through an earlier provider" if $routemarked_interfaces{$interface};
|
||||
fatal_error "The 'track' option requires a numeric value in the MARK column" if $mark eq '-';
|
||||
$routemarked_interfaces{$interface} = $mark;
|
||||
push @routemarked_interfaces, $interface;
|
||||
$track = 1;
|
||||
} elsif ( $option =~ /^balance=(\d+)$/ ) {
|
||||
balance_default_route $1 , $gateway, $interface;
|
||||
} elsif ( $option eq 'balance' ) {
|
||||
@ -261,13 +259,64 @@ sub add_a_provider( $$$$$$$$ ) {
|
||||
$loose = 1;
|
||||
} elsif ( $option eq 'optional' ) {
|
||||
$optional = 1;
|
||||
} elsif ( $option eq 'shared' ) {
|
||||
require_capability 'REALM_MATCH', "The 'shared' option", "s";
|
||||
$shared = 1;
|
||||
} else {
|
||||
fatal_error "Invalid option ($option)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$providers{$table} = { number => $number , mark => $val , optional => $optional };
|
||||
$providers{$table} = { provider => $table, number => $number , mark => $val , optional => $optional , interface => $interface , gateway => $gateway, shared => $shared };
|
||||
|
||||
if ( $track ) {
|
||||
fatal_error "The 'track' option requires a numeric value in the MARK column" if $mark eq '-';
|
||||
|
||||
if ( $routemarked_interfaces{$interface} ) {
|
||||
fatal_error "Interface $interface is tracked through an earlier provider" if $routemarked_interfaces{$interface} > 1;
|
||||
fatal_error "Multiple providers through the same interface must have the 'share' option" unless $shared;
|
||||
} else {
|
||||
$routemarked_interfaces{$interface} = $shared ? 1 : 2;
|
||||
push @routemarked_interfaces, $interface;
|
||||
}
|
||||
|
||||
push @routemarked_providers, $providers{$table};
|
||||
|
||||
}
|
||||
|
||||
my $realm = '';
|
||||
|
||||
if ( $shared ) {
|
||||
fatal_error "The 'shared' option requires a gateway" unless $gateway;
|
||||
|
||||
my $variable = uc( "${interface}_MAC_" . ++$maccount );
|
||||
|
||||
emit "$variable=\$(find_mac $gateway $interface)\n";
|
||||
|
||||
$providers{$table}{mac} = "\$$variable";
|
||||
|
||||
$realm = "realm $number";
|
||||
}
|
||||
|
||||
if ( $duplicate ne '-' ) {
|
||||
if ( $copy eq '-' ) {
|
||||
copy_table ( $duplicate, $number, $realm );
|
||||
} else {
|
||||
if ( $copy eq 'none' ) {
|
||||
$copy = $interface;
|
||||
} else {
|
||||
$copy =~ tr/,/|/;
|
||||
}
|
||||
|
||||
copy_and_edit_table( $duplicate, $number ,$copy , $realm);
|
||||
}
|
||||
} else {
|
||||
fatal_error 'A non-empty COPY column requires that a routing table be specified in the DUPLICATE column' if $copy ne '-';
|
||||
}
|
||||
|
||||
emit "run_ip route replace $gateway src $variable dev $interface table $number $realm";
|
||||
emit "run_ip route add default via $gateway dev $interface table $number $realm";
|
||||
|
||||
if ( $loose ) {
|
||||
if ( $config{DELETE_THEN_ADD} ) {
|
||||
|
@ -904,6 +904,21 @@ find_echo() {
|
||||
|
||||
echo echo
|
||||
}
|
||||
|
||||
#
|
||||
# Determine the MAC address of the passed IP through the passed interface
|
||||
#
|
||||
find_mac() # $1 = IP address, $2 = interface
|
||||
{
|
||||
qt ping -nc 1 -t 2 -I $2 $1
|
||||
|
||||
local result=$(arp -na | awk "/[(]$1[)].* on $2$/ {print \$4}")
|
||||
|
||||
[ -n "$result" -a "$result" != "<incomplete>" ] || fatal_error "Cannot determine the MAC address of $1 through $2"
|
||||
|
||||
echo $result
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# End of functions imported from /usr/share/shorewall/lib.base
|
||||
################################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user