From 892244d31636cb7fec89a52ce76883ef729c4025 Mon Sep 17 00:00:00 2001 From: teastep Date: Mon, 12 Mar 2007 01:04:21 +0000 Subject: [PATCH] Much progress on object generation git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5502 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- New/compiler.pl | 333 +++++++++++++++++++++++++++++++++++++----------- New/lib.base | 5 + New/lib.config | 1 + 3 files changed, 265 insertions(+), 74 deletions(-) diff --git a/New/compiler.pl b/New/compiler.pl index b54fc1131..ff5374dbf 100755 --- a/New/compiler.pl +++ b/New/compiler.pl @@ -107,7 +107,7 @@ my %config = ( STARTUP_ENABLED => undef, # # Config options and global settings that are to be copied to object # -my @propagateconfig = qw/ CLEAR_TC DISABLE_IPV6 ADMINISABSENTMINDED IP_FORWARDING MODULESDIR MODULE_SUFFIX LOGFORMAT /; +my @propagateconfig = qw/ CLEAR_TC DISABLE_IPV6 ADMINISABSENTMINDED IP_FORWARDING MODULESDIR MODULE_SUFFIX LOGFORMAT SUBSYSLOCK/; my @propagateenv = qw/ LOGLIMIT LOGTAGONLY LOGRULENUMBERS /; # # From parsing the capabilities file @@ -142,13 +142,40 @@ my %capabilities = ADDRTYPE => undef, ); +my %capdesc = ( NAT_ENABLED => 'NAT', + MANGLE_ENABLED => 'Packet Mangling', + MULTIPORT => 'Multi-port Match' , + XMULTIPORT => 'Extended Multi-port Match', + CONNTRACK_MATCH => 'Connection Tracking Match', + USEPKTTYPE => 'Packet Type Match', + POLICY_MATCH => 'Policy Match', + PHYSDEV_MATCH => 'Physdev Match', + LENGTH_MATCH => 'Packet length Match', + IPRANGE_MATCH => 'IP Range Match', + RECENT_MATCH => 'Recent Match', + OWNER_MATCH => 'Owner Match', + IPSET_MATCH => 'Ipset Match', + CONNMARK => 'CONNMARK Target', + XCONNMARK => 'Extended CONNMARK Target', + CONNMARK_MATCH => 'Connmark Match', + XCONNMARK_MATCH => 'Extended Connmark Match', + RAW_TABLE => 'Raw Table', + IPP2P_MATCH => 'IPP2P Match', + CLASSIFY_TARGET => 'CLASSIFY Target', + ENHANCED_REJECT => 'Extended Reject', + KLUDGEFREE => 'Repeat match', + MARK => 'MARK Target', + XMARK => 'Extended Mark Target', + MANGLE_FORWARD => 'Mangle FORWARD Chain', + COMMENTS => 'Comments', + ADDRTYPE => 'Address Type Match', + ); + my ( $command, $doing, $done ) = qw/ compile Compiling Compiled/; #describe the current command, it's present progressive, and it's completion. -my $line; # Current config file line - -my $object; # Object file Handle Reference - -my $tempfile; # Temporary object file name +my $line = ''; # Current config file line +my $object = 0; # Object file Handle Reference +my $tempfile = ''; # Temporary object file name # @@ -385,7 +412,7 @@ sub fatal_error print STDERR " ERROR: @_\n"; close $object, if $object; system "rm -rf $ENV{TMP_DIR}" if $ENV{TMP_DIR}; - exit 2; + die; } sub progress_message { @@ -450,7 +477,7 @@ sub emit ( $ ) { # sub emit_unindented( $ ) { - print $object $_[0]; + print $object "$_[0]\n"; } # @@ -5400,10 +5427,6 @@ sub do_initialize() { $env{MAXZONENAMELENGTH} = 5; } - fatal_error "Shorewall $env{VERSION} requires Conntrack Match Support" unless $capabilities{CONNTRACK_MATCH}; - fatal_error "Shorewall $env{VERSION} requires Extended Multi-port Match Support" unless $capabilities{XMULTIPORT}; - fatal_error "Shorewall $env{VERSION} requires Address Type Match Support" unless $capabilities{ADDRTYPE}; - if ( $ENV{DEBUG} ) { print "\n"; print "Configuration:\n"; @@ -5427,6 +5450,205 @@ sub do_initialize() { initialize_chain_table; } +sub setup_forwarding() { + if ( "\L$config{IP_FORWARDING}" eq 'on' ) { + emit 'echo 1 > /proc/sys/net/ipv4/ip_forward'; + emit 'progress_message2 IP Forwarding Enabled'; + } elsif ( "\L$config{IP_FORWARDING}" eq 'off' ) { + emit 'echo 0 > /proc/sys/net/ipv4/ip_forward'; + emit 'progress_message2 IP Forwarding Disabled!'; + } +} + +sub generate_object () { + copy find_file 'prog.header'; + + my $date = localtime; + + emit "#\n# Compiled firewall script generated by Shorewall $ENV{VERSION} - $date\n#"; + + if ( $ENV{EXPORT} ) { + emit 'SHAREDIR=/usr/share/shorewall-lite'; + emit 'CONFDIR=/etc/shorewall-lite'; + emit 'VARDIR=/var/lib/shorewall-lite'; + emit 'PRODUCT="Shorewall Lite"'; + + copy "$env{SHAREDIR}/lib.base"; + + emit '################################################################################'; + emit '# End of /usr/share/shorewall/lib.base'; + emit '################################################################################'; + } else { + emit 'SHAREDIR=/usr/share/shorewall'; + emit 'CONFDIR=/etc/shorewall'; + emit 'VARDIR=/var/lib/shorewall\n'; + emit 'PRODUCT=\'Shorewall\''; + emit '. /usr/share/shoreall-lite/lib.base'; + } + + emit ''; + + for my $exit qw/init start started stop stopped/ { + emit "run_${exit}_exit() {"; + $indent = ' '; + append_file $exit; + $indent = ''; + emit "}\n"; + } + + emit 'initialize()'; + emit '{'; + + $indent = ' '; + + if ( $ENV{EXPORT} ) { + emit '#'; + emit '# These variables are required by the library functions called in this script'; + emit '#'; + emit 'CONFIG_PATH="/etc/shorewall-lite:/usr/share/shorewall-lite"'; + } else { + emit 'if [ ! -f ${SHAREDIR}/version ]; then'; + emit ' fatal_error "This script requires Shorewall which do not appear to be installed on this system (did you forget \"-e\" when you compiled?)"'; + emit 'fi'; + emit ''; + emit 'local version=\$(cat \${SHAREDIR}/version)'; + emit ''; + emit 'if [ ${SHOREWALL_LIBVERSION:-0} -lt 30203 ]; then'; + emit ' fatal_error "This script requires Shorewall version 3.3.3 or later; current version is $version"'; + emit 'fi'; + emit '#'; + emit '# These variables are required by the library functions called in this script'; + emit '#'; + emit "CONFIG_PATH=\"$config{CONFIG_PATH}\""; + } + + for my $option ( @propagateconfig ) { + my $value = $config{$option} || ''; + emit "${option}=\"${value}\""; + } + + for my $option ( @propagateenv ) { + my $value = $env{$option} || ''; + emit "${option}=\"${value}\""; + } + + emit '[ -n "${COMMAND:=restart}" ]'; + emit '[ -n "${VERBOSE:=0}" ]'; + emit '[ -n "${RESTOREFILE:=$RESTOREFILE}" ]'; + emit '[ -n "$LOGFORMAT" ] || LOGFORMAT="Shorewall:%s:%s:"'; + emit "VERSION=\"$ENV{VERSION}\""; + emit "PATH=\"$config{PATH}\""; + emit 'TERMINATOR=fatal_error'; + + if ( $config{IPTABLES} ) { + emit "IPTABLES=\"$config{IPTABLES}\"\n"; + emit "[ -x \"$config{IPTABLES}\" ] || startup_error \"IPTABLES=$config{IPTABLES} does not exist or is not executable\""; + } else { + emit '[ -z "$IPTABLES" ] && IPTABLES=$(mywhich iptables 2> /dev/null)'; + emit ''; + emit '[ -n "$IPTABLES" -a -x "$IPTABLES" ] || startup_error "Can\'t find iptables executable"'; + } + + emit ''; + emit "STOPPING="; + emit "COMMENT=\n"; # Fixme -- eventually this goes but it's ok now to maintain compability with lib.base + emit '#'; + emit '# The library requires that ${VARDIR} exist'; + emit '#'; + emit '[ -d ${VARDIR} ] || mkdir -p ${VARDIR}'; + + $indent = ''; + + emit "}\n"; + + copy find_file 'prog.functions'; + progress_message2 "Creating iptables-restore input..."; create_iptables_restore_file; + + emit '#'; + emit '# Start/Restart/Reload the firewall'; + emit '#'; + emit 'define_firewall() {'; + + $indent = ' '; + + emit 'local restore_file=$1'; + + save_progress_message 'Initializing...'; + + if ( $ENV{EXPORT} ) { + my $mf = find_file 'modules'; + + if ( $mf ne "$env{SHAREDIR}/module" && -f $mf ) { + + emit 'echo MODULESDIR="$MODULESDIR" > ${VARDIR}/.modulesdir'; + emit 'cat > ${VARDIR}/.modules << EOF'; + + open MF, $mf or fatal_error "Unable to open $mf: $!"; + + while ( $line = ) { print $object $line if $line =~ /^\s*loadmodule\b/; } + + close MF; + + emit_unindented "EOF\n"; + + emit 'reload_kernel_modules < ${VARDIR}/.modules'; + } else { + emit 'load_kernel_modules Yes'; + } + } else { + emit 'load_kernel_modules Yes'; + } + + emit ''; + + for my $interface ( @{find_interfaces_by_option 'norfc1918'} ) { + emit "addr=\$(ip -f inet addr show $interface 2> /dev/null | grep 'inet\ ' | head -n1)"; + emit 'if [ -n "$addr" ]; then'; + emit " addr=\$(echo \$addr | sed 's/inet //;s/\/.*//;s/ peer.*//')"; + emit ' for network in 10.0.0.0/8 176.16.0.0/12 192.168.0.0/16; do'; + emit ' if in_network $addr $network; then'; + emit " startup_error \"The 'norfc1918' option has been specified on an interface with an RFC 1918 address. Interface:$interface\""; + emit ' fi'; + emit ' done'; + emit 'fi'; + } + + emit "run_init_exit\n"; + emit "delete_proxyarp\n"; + emit '[ -n "$CLEAR_TC" ] && delete_tc1'; + emit ''; + emit '[ -n "$DISABLE_IPV6" ] && disable_ipv6'; + emit ''; + emit "undo_routing\n"; + emit "restore_default_route\n"; + + emit "f=\$(find_file ipsets)\n"; + + emit 'if [ -f $f ]; then'; + emit ' progress_message2 "Restoring IPSETS...'; + emit ' ipset -U :all: :all:'; + emit ' ipset -F'; + emit ' ipset -X'; + emit ' ipset -R < $f'; + emit "fi\n"; + + emit "disable_ipv6\n" if $config{DISABLE_IPV6}; + + setup_forwarding; + + $indent = ''; + + emit '}'; + + copy find_file 'prog.footer'; +} + +sub report_capability( $ ) { + my $cap = $_[0]; + print " $capdesc{$cap}: "; + print $capabilities{$cap} ? "Available\n" : "Not Available\n"; +} + sub compile_firewall( $ ) { my $objectfile = $_[0]; @@ -5442,71 +5664,28 @@ sub compile_firewall( $ ) { fatal_error "$objectfile is a Directory" if -d $objectfile; fatal_error "$dir is a Symbolic Link" if -l $objectfile; fatal_error "$objectfile exists and is not a compiled script" if -e _ && ! -x _; - - ( $object, $tempfile ) = tempfile ( 'tempfileXXXX' , DIR => $dir ); - + $file = "$file.$suffix" if $suffix; }; fatal_error "$@" if $@; - - copy find_file 'prog.header'; - - my $date = localtime; - - emit "#\n# Compiled firewall script generated by Shorewall $env{VERSION} - $date\n#"; - - if ( $ENV{EXPORT} ) { - emit 'SHAREDIR=/usr/share/shorewall-lite'; - emit 'CONFDIR=/etc/shorewall-lite'; - emit 'VARDIR=/var/lib/shorewall-lite'; - emit 'PRODUCT="Shorewall Lite"'; - - copy "$env{SHAREDIR}/lib.base"; - - emit '################################################################################'; - emit '# End of /usr/share/shorewall/lib.base'; - emit '################################################################################'; - } else { - emit 'SHAREDIR=/usr/share/shorewall'; - emit 'CONFDIR=/etc/shorewall'; - emit 'VARDIR=/var/lib/shorewall\n'; - emit 'PRODUCT=\'Shorewall\''; - emit '. /usr/share/shoreall-lite/lib.base'; - } - - emit ''; - - for my $exit qw/init initdone start started stop stopped/ { - emit "run_${exit}_exit() {"; - $indent = ' '; - append_file $exit; - $indent = ''; - emit "}\n"; - } - - emit 'initialize()'; - emit '{'; - - $indent = ' '; - - for my $option ( @propagateconfig ) { - my $value = $config{$option} || ''; - emit "${option}=\"${value}\""; - } - - for my $option ( @propagateenv ) { - my $value = $env{$option} || ''; - emit "${option}=\"${value}\""; - } - - emit '}'; - - $indent = ''; - - copy find_file 'prog.functions'; } + if ( $ENV{VERBOSE} > 1 ) { + print "Shorewall has detected the following capabilities:\n"; + + for my $cap ( sort { $capdesc{$a} cmp $capdesc{$b} } keys %capabilities ) { + report_capability $cap; + } + } + + fatal_error "Shorewall $ENV{VERSION} requires Conntrack Match Support" unless $capabilities{CONNTRACK_MATCH}; + fatal_error "Shorewall $ENV{VERSION} requires Extended Multi-port Match Support" unless $capabilities{XMULTIPORT}; + fatal_error "Shorewall $ENV{VERSION} requires Address Type Match Support" unless $capabilities{ADDRTYPE}; + fatal_error 'BRIDGING=Yes requires Physdev Match support in your Kernel and iptables' if $config{BRIDGING} && ! $capabilities{PHYSDEV_MATCH}; + fatal_error 'MACLIST_TTL requires the Recent Match capability which is not present in your Kernel and/or iptables' if $config{MACLIST_TTL} && ! $capabilities{RECENT_MATCH}; + fatal_error 'RFC1918_STRICT=Yes requires Connection Tracking match' if $config{RFC1918_STRICT} && ! $capabilities{CONNTRACK_MATCH}; + # # Process the zones file. # @@ -5522,7 +5701,7 @@ sub compile_firewall( $ ) { if ( $ENV{DEBUG} ) { dump_zone_info; - } else { + } elsif ( $ENV{VERBOSE} > 1 ) { progress_message "Determining Hosts in Zones..."; zone_report; } # @@ -5586,8 +5765,14 @@ sub compile_firewall( $ ) { # Create the script. # unless ( $command eq 'check' ) { - progress_message2 "Creating iptables-restore input..."; create_iptables_restore_file; - copy find_file 'prog.footer'; + eval { + ( $object, $tempfile ) = tempfile ( 'tempfileXXXX' , DIR => $dir ); + }; + + fatal_error "$@" if $@; + + generate_object; + $file = "$dir/$file"; rename $tempfile, $file; chmod 0700, $file; diff --git a/New/lib.base b/New/lib.base index 9c3fd7d02..b70f83e8e 100644 --- a/New/lib.base +++ b/New/lib.base @@ -339,6 +339,11 @@ lib_load() # $1 = Name of the Library, $2 = Error Message heading if the library eval loaded=\$LIB_${1}_LOADED if [ -z "$loaded" ]; then + if [ -n "$EXPERIMENTAL" ]; then + eval LIB_${1}_LOADED=Yes + return + fi + if [ -f $lib ]; then progress_message "Loading library $lib..." . $lib diff --git a/New/lib.config b/New/lib.config index 801d31c81..0260c0ed9 100644 --- a/New/lib.config +++ b/New/lib.config @@ -2181,6 +2181,7 @@ do_initialize() { report_capabilities1 > $TMP_DIR/capabilities export TMP_DIR export CONFIG_PATH + export VERSION fi # # Clear $FW