2009-02-22 18:30:14 +01:00
#
2009-06-13 16:07:55 +02:00
# Shorewall 4.4 -- /usr/share/shorewall/Shorewall/Config.pm
2009-02-22 18:30:14 +01:00
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
2013-01-12 01:01:10 +01:00
# (c) 2007,2008,2009,2010,2011,2012,2013 - Tom Eastep (teastep@shorewall.net)
2009-02-22 18:30:14 +01:00
#
# Complete documentation is available at http://shorewall.net
#
2014-01-04 18:48:27 +01:00
# This program is part of Shorewall.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 2 of the license or, at your
# option, any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
2009-02-22 18:30:14 +01:00
#
# This module is responsible for lower level configuration file handling.
# It also exports functions for generating warning and error messages.
# The get_configuration function parses the shorewall.conf, capabilities and
# modules files during compiler startup. The module also provides the basic
2009-10-06 00:43:29 +02:00
# output file services such as creation of temporary 'script' files, writing
2009-02-22 18:30:14 +01:00
# into those files (emitters) and finalizing those files (renaming
# them to their final name and setting their mode appropriately).
#
package Shorewall::Config ;
use strict ;
use warnings ;
use File::Basename ;
use File::Temp qw/ tempfile tempdir / ;
use Cwd qw( abs_path getcwd ) ;
2012-08-29 20:35:11 +02:00
use autouse 'Carp' = > qw( longmess confess ) ;
2009-02-22 18:30:14 +01:00
use Scalar::Util 'reftype' ;
2011-04-03 18:56:30 +02:00
use FindBin ;
2014-10-31 02:38:45 +01:00
use Digest::SHA qw( sha1_hex ) ;
2009-02-22 18:30:14 +01:00
our @ ISA = qw( Exporter ) ;
#
2012-08-29 20:35:11 +02:00
# Imported variables should be treated as read-only by importers
#
2009-02-22 18:30:14 +01:00
our @ EXPORT = qw(
warning_message
fatal_error
2009-03-09 21:56:53 +01:00
assert
2012-11-28 01:17:43 +01:00
currentlineinfo
2013-07-24 16:22:51 +02:00
shortlineinfo
2013-06-01 22:03:10 +02:00
clear_currentfilename
2013-07-17 19:19:18 +02:00
validate_level
2012-04-24 23:52:57 +02:00
2009-02-22 18:30:14 +01:00
progress_message
progress_message_nocompress
progress_message2
progress_message3
2012-04-24 23:52:57 +02:00
2011-06-12 00:40:55 +02:00
supplied
2012-05-15 02:12:46 +02:00
split_list
2012-04-24 23:52:57 +02:00
2013-05-27 15:52:45 +02:00
shorewall
2011-06-22 15:53:15 +02:00
get_action_params
2011-07-02 16:02:18 +02:00
get_action_chain
2013-01-19 19:52:11 +01:00
get_action_chain_name
2013-07-10 22:27:58 +02:00
set_action_name_to_caller
2013-01-18 22:06:55 +01:00
get_action_logging
2013-01-19 19:52:11 +01:00
get_action_disposition
2013-07-10 22:27:58 +02:00
set_action_disposition
2011-06-11 17:33:21 +02:00
set_action_param
2013-12-16 21:31:35 +01:00
fetch_inline_matches
2013-07-10 22:27:58 +02:00
set_inline_matches
2012-04-24 23:52:57 +02:00
2013-09-23 21:21:44 +02:00
set_comment
push_comment
pop_comment
2011-07-03 15:22:51 +02:00
have_capability
require_capability
2013-02-18 17:48:18 +01:00
report_used_capabilities
2012-08-04 04:26:02 +02:00
kernel_version
2009-02-22 18:30:14 +01:00
) ;
2011-12-02 16:36:23 +01:00
our @ EXPORT_OK = qw( $shorewall_dir initialize shorewall ) ;
2009-02-22 18:30:14 +01:00
2009-10-06 00:43:29 +02:00
our % EXPORT_TAGS = ( internal = > [ qw( create_temp_script
2014-10-31 02:38:45 +01:00
generate_sha1
2009-10-06 00:43:29 +02:00
finalize_script
enable_script
disable_script
2009-02-22 18:30:14 +01:00
numeric_value
numeric_value1
2011-05-02 18:52:31 +02:00
normalize_hex
2009-04-23 21:43:57 +02:00
hex_value
2009-02-22 18:30:14 +01:00
in_hex
in_hex2
in_hex3
in_hex4
in_hex8
2009-04-23 21:43:57 +02:00
in_hexp
2009-02-22 18:30:14 +01:00
emit
2010-01-11 23:16:03 +01:00
emitstd
2009-02-22 18:30:14 +01:00
emit_unindented
save_progress_message
save_progress_message_short
set_timestamp
2009-08-22 16:57:55 +02:00
set_verbosity
2009-02-22 18:30:14 +01:00
set_log
2011-12-02 16:36:23 +01:00
set_config_path
2009-02-22 18:30:14 +01:00
close_log
set_command
push_indent
pop_indent
copy
2009-06-19 23:39:45 +02:00
copy1
2010-03-06 16:40:43 +01:00
copy2
2009-02-22 18:30:14 +01:00
create_temp_aux_config
finalize_aux_config
set_shorewall_dir
set_debug
find_file
2015-08-31 20:21:18 +02:00
find_writable_file
2009-02-22 18:30:14 +01:00
split_list
split_list1
2012-12-02 00:06:51 +01:00
split_list2
2009-02-22 18:30:14 +01:00
split_line
split_line1
2013-12-14 22:35:01 +01:00
split_line2
2009-02-22 18:30:14 +01:00
first_entry
open_file
close_file
push_open
pop_open
2011-06-11 16:46:54 +02:00
push_action_params
pop_action_params
default_action_params
2009-02-22 18:30:14 +01:00
read_a_line
2010-03-27 15:33:40 +01:00
which
2009-02-22 18:30:14 +01:00
qt
ensure_config_path
2011-01-09 22:12:36 +01:00
add_param
2011-01-09 21:14:48 +01:00
export_params
2009-02-22 18:30:14 +01:00
get_configuration
report_capabilities
propagateconfig
append_file
run_user_exit
run_user_exit1
run_user_exit2
generate_aux_config
2012-12-23 19:50:31 +01:00
format_warning
2012-12-22 22:51:24 +01:00
no_comment
macro_comment
2011-11-20 21:29:17 +01:00
dump_mark_layout
2013-11-18 15:57:54 +01:00
set_section_function
clear_section_function
2014-02-17 21:50:59 +01:00
directive_callback
2009-02-22 18:30:14 +01:00
$ product
$ Product
2010-08-24 17:38:49 +02:00
$ toolname
2009-02-22 18:30:14 +01:00
$ command
$ doing
$ done
$ currentline
2011-12-28 19:29:15 +01:00
$ currentfilename
2010-03-28 22:09:04 +02:00
$ debug
2012-12-22 00:14:23 +01:00
$ file_format
2012-12-22 22:51:24 +01:00
$ comment
2013-04-09 02:30:00 +02:00
2009-02-22 18:30:14 +01:00
% config
% globals
2011-02-18 01:31:22 +01:00
% config_files
2012-03-24 21:05:39 +01:00
% shorewallrc
2012-09-04 05:09:20 +02:00
% shorewallrc1
2009-02-22 18:30:14 +01:00
2012-08-03 19:53:20 +02:00
% helpers
2012-08-03 00:38:23 +02:00
% helpers_map
2012-08-03 19:53:20 +02:00
% helpers_enabled
2012-08-07 00:54:45 +02:00
% helpers_aliases
2013-01-19 19:52:11 +01:00
% actparms
2012-08-03 00:38:23 +02:00
2009-02-22 18:30:14 +01:00
F_IPV4
F_IPV6
2012-08-03 19:53:20 +02:00
TCP
UDP
UDPLITE
ICMP
DCCP
IPv6_ICMP
SCTP
GRE
2009-02-22 18:30:14 +01:00
MIN_VERBOSITY
MAX_VERBOSITY
2012-04-10 22:51:25 +02:00
2012-04-11 02:01:38 +02:00
PLAIN_READ
2012-04-10 22:51:25 +02:00
EMBEDDED_ENABLED
EXPAND_VARIABLES
STRIP_COMMENTS
SUPPRESS_WHITESPACE
2012-04-11 02:01:38 +02:00
CONFIG_CONTINUATION
DO_INCLUDE
2013-11-18 15:57:54 +01:00
DO_SECTION
2012-04-14 17:04:28 +02:00
NORMAL_READ
2013-07-29 19:08:35 +02:00
OPTIMIZE_POLICY_MASK
OPTIMIZE_POLICY_MASK2n4
OPTIMIZE_RULESET_MASK
OPTIMIZE_USE_FIRST
OPTIMIZE_ALL
2012-09-17 16:52:18 +02:00
) , ] ,
2012-08-03 19:53:20 +02:00
protocols = > [ qw (
TCP
UDP
UDPLITE
ICMP
DCCP
IPv6_ICMP
SCTP
GRE
2012-09-17 16:52:18 +02:00
) , ] ,
2012-08-03 19:53:20 +02:00
) ;
2009-02-22 18:30:14 +01:00
Exporter:: export_ok_tags ( 'internal' ) ;
2015-04-28 20:59:01 +02:00
our $ VERSION = 'MODULEVERSION' ;
2009-02-22 18:30:14 +01:00
#
# describe the current command, it's present progressive, and it's completion.
#
our ( $ command , $ doing , $ done ) ;
#
# VERBOSITY
#
2012-12-23 22:16:54 +01:00
our $ verbosity ;
2009-02-22 18:30:14 +01:00
#
# Logging
#
2012-12-23 22:16:54 +01:00
our ( $ log , $ log_verbosity ) ;
2009-02-22 18:30:14 +01:00
#
# Timestamp each progress message, if true.
#
2012-12-23 22:16:54 +01:00
our $ timestamp ;
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# Script (output) file handle
2009-02-22 18:30:14 +01:00
#
2012-12-23 22:16:54 +01:00
our $ script ;
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# When 'true', writes to the script are enabled. Used to catch code emission between functions
2009-04-07 05:22:30 +02:00
#
2012-12-23 22:16:54 +01:00
our $ script_enabled ;
2009-04-07 05:22:30 +02:00
#
2009-02-22 18:30:14 +01:00
# True, if last line emitted is blank
#
2012-12-23 22:16:54 +01:00
our $ lastlineblank ;
2009-02-22 18:30:14 +01:00
#
# Tabs to indent the output
#
2012-12-23 22:16:54 +01:00
our $ indent1 ;
2009-02-22 18:30:14 +01:00
#
# Characters to indent the output
#
2012-12-23 22:16:54 +01:00
our $ indent2 ;
2009-02-22 18:30:14 +01:00
#
# Total indentation
#
2012-12-23 22:16:54 +01:00
our $ indent ;
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# Script's Directory and File
2009-02-22 18:30:14 +01:00
#
2012-12-23 22:16:54 +01:00
our ( $ dir , $ file ) ;
2009-02-22 18:30:14 +01:00
#
# Temporary output file's name
#
2012-12-23 22:16:54 +01:00
our $ tempfile ;
2009-02-22 18:30:14 +01:00
#
2011-06-18 22:03:55 +02:00
# Fully qualified name of the configuration file
#
2012-12-23 22:16:54 +01:00
our $ configfile ;
2011-06-18 22:03:55 +02:00
#
2011-05-15 17:45:41 +02:00
# Misc Globals exported to other modules
2009-02-22 18:30:14 +01:00
#
our % globals ;
#
2011-05-15 17:45:41 +02:00
# From shorewall.conf file - exported to other modules.
2009-02-22 18:30:14 +01:00
#
our % config ;
2011-06-19 01:55:00 +02:00
#
2012-08-02 20:06:41 +02:00
# Entries in shorewall.conf that have been renamed
#
2013-02-12 16:47:02 +01:00
our % renamed = ( AUTO_COMMENT = > 'AUTOCOMMENT' , BLACKLIST_LOGLEVEL = > 'BLACKLIST_LOG_LEVEL' ) ;
2012-08-02 20:06:41 +02:00
#
2009-10-06 00:43:29 +02:00
# Config options and global settings that are to be copied to output script
2009-02-22 18:30:14 +01:00
#
2015-10-12 23:08:24 +02:00
our @ propagateconfig = qw/ DISABLE_IPV6 MODULESDIR MODULE_SUFFIX LOAD_HELPERS_ONLY LOCKFILE SUBSYSLOCK LOG_VERBOSITY RESTART/ ;
2009-02-22 18:30:14 +01:00
#
2009-03-16 17:37:21 +01:00
# From parsing the capabilities file or detecting capabilities
2009-02-22 18:30:14 +01:00
#
2012-12-23 22:16:54 +01:00
our % capabilities ;
2009-02-22 18:30:14 +01:00
#
# Capabilities
#
2012-12-23 22:16:54 +01:00
our % capdesc = ( NAT_ENABLED = > 'NAT' ,
2009-02-22 18:30:14 +01:00
MANGLE_ENABLED = > 'Packet Mangling' ,
MULTIPORT = > 'Multi-port Match' ,
XMULTIPORT = > 'Extended Multi-port Match' ,
2013-03-10 17:04:47 +01:00
EMULTIPORT = > 'Enhanced Multi-port Match' ,
2009-02-22 18:30:14 +01:00
CONNTRACK_MATCH = > 'Connection Tracking Match' ,
2009-08-20 23:32:15 +02:00
OLD_CONNTRACK_MATCH = >
2009-02-22 18:30:14 +01:00
'Old conntrack match syntax' ,
2009-08-20 23:32:15 +02:00
NEW_CONNTRACK_MATCH = >
2009-02-22 18:30:14 +01:00
'Extended Connection Tracking Match' ,
USEPKTTYPE = > 'Packet Type Match' ,
POLICY_MATCH = > 'Policy Match' ,
PHYSDEV_MATCH = > 'Physdev Match' ,
PHYSDEV_BRIDGE = > 'Physdev-is-bridged support' ,
LENGTH_MATCH = > 'Packet length Match' ,
IPRANGE_MATCH = > 'IP Range Match' ,
RECENT_MATCH = > 'Recent Match' ,
2013-10-07 16:54:52 +02:00
REAP_OPTION = > 'Recent Match "--reap" option' ,
2009-02-22 18:30:14 +01:00
OWNER_MATCH = > 'Owner Match' ,
2012-03-26 05:18:20 +02:00
OWNER_NAME_MATCH
= > 'Owner Name Match' ,
2009-02-22 18:30:14 +01:00
IPSET_MATCH = > 'Ipset Match' ,
2010-08-04 06:06:17 +02:00
OLD_IPSET_MATCH = > 'Old Ipset Match' ,
2014-01-02 18:36:35 +01:00
IPSET_MATCH_NOMATCH
= > 'Ipset Match nomatch' ,
IPSET_MATCH_COUNTERS
= > 'Ipset Match counters' ,
2011-07-16 18:41:53 +02:00
IPSET_V5 = > 'Version 5 ipsets' ,
2009-02-22 18:30:14 +01:00
CONNMARK = > 'CONNMARK Target' ,
XCONNMARK = > 'Extended CONNMARK Target' ,
CONNMARK_MATCH = > 'Connmark Match' ,
XCONNMARK_MATCH = > 'Extended Connmark Match' ,
RAW_TABLE = > 'Raw Table' ,
IPP2P_MATCH = > 'IPP2P Match' ,
OLD_IPP2P_MATCH = > 'Old IPP2P Match Syntax' ,
CLASSIFY_TARGET = > 'CLASSIFY Target' ,
ENHANCED_REJECT = > 'Extended Reject' ,
KLUDGEFREE = > 'Repeat match' ,
MARK = > 'MARK Target' ,
XMARK = > 'Extended Mark Target' ,
2010-01-13 02:01:20 +01:00
EXMARK = > 'Extended Mark Target 2' ,
2009-02-22 18:30:14 +01:00
MANGLE_FORWARD = > 'Mangle FORWARD Chain' ,
COMMENTS = > 'Comments' ,
ADDRTYPE = > 'Address Type Match' ,
TCPMSS_MATCH = > 'TCPMSS Match' ,
HASHLIMIT_MATCH = > 'Hashlimit Match' ,
NFQUEUE_TARGET = > 'NFQUEUE Target' ,
REALM_MATCH = > 'Realm Match' ,
HELPER_MATCH = > 'Helper Match' ,
CONNLIMIT_MATCH = > 'Connlimit Match' ,
TIME_MATCH = > 'Time Match' ,
GOTO_TARGET = > 'Goto Support' ,
2009-06-25 22:50:27 +02:00
LOG_TARGET = > 'LOG Target' ,
2011-11-12 23:10:48 +01:00
ULOG_TARGET = > 'ULOG Target' ,
NFLOG_TARGET = > 'NFLOG Target' ,
2009-04-12 17:22:19 +02:00
LOGMARK_TARGET = > 'LOGMARK Target' ,
2009-04-19 17:46:57 +02:00
IPMARK_TARGET = > 'IPMARK Target' ,
2009-08-15 17:35:54 +02:00
PERSISTENT_SNAT = > 'Persistent SNAT' ,
2009-09-23 22:56:31 +02:00
OLD_HL_MATCH = > 'Old Hash Limit Match' ,
2010-01-17 17:15:14 +01:00
TPROXY_TARGET = > 'TPROXY Target' ,
2010-02-10 23:50:26 +01:00
FLOW_FILTER = > 'Flow Classifier' ,
2010-07-04 18:08:04 +02:00
FWMARK_RT_MASK = > 'fwmark route mask' ,
2013-07-12 18:45:20 +02:00
MARK_ANYWHERE = > 'Mark in the filter table' ,
2010-11-24 19:46:06 +01:00
HEADER_MATCH = > 'Header Match' ,
2011-01-29 23:18:53 +01:00
ACCOUNT_TARGET = > 'ACCOUNT Target' ,
2011-05-20 16:47:35 +02:00
AUDIT_TARGET = > 'AUDIT Target' ,
2011-08-13 20:14:29 +02:00
RAWPOST_TABLE = > 'Rawpost Table' ,
2011-09-22 00:20:50 +02:00
CONDITION_MATCH = > 'Condition Match' ,
2011-10-01 22:54:52 +02:00
IPTABLES_S = > 'iptables -S' ,
2011-11-01 14:34:57 +01:00
BASIC_FILTER = > 'Basic Filter' ,
2014-01-03 18:35:34 +01:00
BASIC_EMATCH = > 'Basic Filter ematch' ,
2011-12-04 23:35:53 +01:00
CT_TARGET = > 'CT Target' ,
2012-04-24 23:52:57 +02:00
STATISTIC_MATCH = >
2012-01-05 00:46:01 +01:00
'Statistics Match' ,
2012-02-02 21:54:00 +01:00
IMQ_TARGET = > 'IMQ Target' ,
2012-02-20 17:47:48 +01:00
DSCP_MATCH = > 'DSCP Match' ,
DSCP_TARGET = > 'DSCP Target' ,
2012-05-15 02:12:46 +02:00
GEOIP_MATCH = > 'GeoIP Match' ,
2012-07-28 17:19:05 +02:00
RPFILTER_MATCH = > 'RPFilter Match' ,
NFACCT_MATCH = > 'NFAcct Match' ,
2012-10-23 00:42:13 +02:00
CHECKSUM_TARGET = > 'Checksum Target' ,
2013-01-04 18:17:57 +01:00
ARPTABLESJF = > 'Arptables JF' ,
2013-02-27 18:25:26 +01:00
MASQUERADE_TGT = > 'MASQUERADE Target' ,
2013-03-10 18:07:52 +01:00
UDPLITEREDIRECT = > 'UDPLITE Port Redirection' ,
2013-04-09 23:04:16 +02:00
NEW_TOS_MATCH = > 'New tos Match' ,
2014-12-29 00:23:30 +01:00
TARPIT_TARGET = > 'TARPIT Target' ,
2015-01-02 18:05:06 +01:00
IFACE_MATCH = > 'Iface Match' ,
2015-04-01 00:53:05 +02:00
TCPMSS_TARGET = > 'TCPMSS Target' ,
2013-03-10 17:04:47 +01:00
2012-08-03 00:38:23 +02:00
AMANDA_HELPER = > 'Amanda Helper' ,
FTP_HELPER = > 'FTP Helper' ,
2012-08-07 00:54:45 +02:00
FTP0_HELPER = > 'FTP-0 Helper' ,
2012-08-03 19:53:20 +02:00
H323_HELPER = > 'H323 Helpers' ,
2012-08-03 00:38:23 +02:00
IRC_HELPER = > 'IRC Helper' ,
2012-08-07 00:54:45 +02:00
IRC0_HELPER = > 'IRC-0 Helper' ,
2012-08-03 00:38:23 +02:00
NETBIOS_NS_HELPER = >
2012-08-03 19:53:20 +02:00
'Netbios-ns Helper' ,
2012-08-03 00:38:23 +02:00
PPTP_HELPER = > 'PPTP Helper' ,
2012-08-07 00:54:45 +02:00
SANE_HELPER = > 'SANE Helper' ,
SANE0_HELPER = > 'SANE-0 Helper' ,
2012-08-03 00:38:23 +02:00
SIP_HELPER = > 'SIP Helper' ,
2012-08-07 00:54:45 +02:00
SIP0_HELPER = > 'SIP-0 Helper' ,
2012-08-03 00:38:23 +02:00
SNMP_HELPER = > 'SNMP Helper' ,
TFTP_HELPER = > 'TFTP Helper' ,
2015-01-03 18:22:40 +01:00
TFTP0_HELPER = > 'TFTP-0 Helper' ,
2012-06-02 23:06:31 +02:00
#
# Constants
#
LOG_OPTIONS = > 'Log Options' ,
2009-02-22 18:30:14 +01:00
CAPVERSION = > 'Capability Version' ,
2009-12-19 21:42:39 +01:00
KERNELVERSION = > 'Kernel Version' ,
2009-02-22 18:30:14 +01:00
) ;
2011-02-18 01:31:22 +01:00
2013-02-18 17:48:18 +01:00
our % used ;
2013-07-02 00:36:16 +02:00
use constant {
USED = > 1 ,
REQUIRED = > 2 } ;
2012-08-03 19:53:20 +02:00
use constant {
ICMP = > 1 ,
TCP = > 6 ,
UDP = > 17 ,
DCCP = > 33 ,
GRE = > 47 ,
IPv6_ICMP = > 58 ,
SCTP = > 132 ,
UDPLITE = > 136 ,
} ;
2013-07-29 19:08:35 +02:00
#
# Optimization masks
#
use constant {
OPTIMIZE_POLICY_MASK = > 0x02 , # Call optimize_policy_chains()
OPTIMIZE_POLICY_MASK2n4 = > 0x06 ,
OPTIMIZE_RULESET_MASK = > 0x1C , # Call optimize_ruleset()
OPTIMIZE_ALL = > 0x1F , # Maximum value for documented categories.
OPTIMIZE_USE_FIRST = > 0x1000 # Always use interface 'first' chains -- undocumented
} ;
2012-08-03 19:53:20 +02:00
our % helpers = ( amanda = > UDP ,
ftp = > TCP ,
irc = > TCP ,
'netbios-ns' = > UDP ,
pptp = > TCP ,
'Q.931' = > TCP ,
RAS = > UDP ,
sane = > TCP ,
sip = > UDP ,
snmp = > UDP ,
tftp = > UDP ,
) ;
2012-08-07 00:54:45 +02:00
our % helpers_map ;
2012-08-03 00:38:23 +02:00
2012-08-03 19:53:20 +02:00
our % helpers_names ;
2012-08-07 00:54:45 +02:00
our % helpers_aliases ;
2012-08-03 19:53:20 +02:00
our % helpers_enabled ;
2011-02-18 02:35:56 +01:00
our % config_files = ( #accounting => 1,
2011-02-18 01:31:22 +01:00
actions = > 1 ,
blacklist = > 1 ,
clear = > 1 ,
2012-08-02 20:02:17 +02:00
conntrack = > 1 ,
2011-02-18 01:31:22 +01:00
ecn = > 1 ,
findgw = > 1 ,
hosts = > 1 ,
init = > 1 ,
initdone = > 1 ,
interfaces = > 1 ,
isusable = > 1 ,
maclist = > 1 ,
masq = > 1 ,
nat = > 1 ,
netmap = > 1 ,
params = > 1 ,
policy = > 1 ,
providers = > 1 ,
proxyarp = > 1 ,
refresh = > 1 ,
refreshed = > 1 ,
restored = > 1 ,
2011-08-14 21:01:17 +02:00
rawnat = > 1 ,
2011-02-18 01:31:22 +01:00
route_rules = > 1 ,
routes = > 1 ,
routestopped = > 1 ,
2012-08-02 20:02:17 +02:00
rtrules = > 1 ,
2011-02-18 01:31:22 +01:00
rules = > 1 ,
scfilter = > 1 ,
secmarks = > 1 ,
start = > 1 ,
started = > 1 ,
stop = > 1 ,
stopped = > 1 ,
2012-09-03 17:44:03 +02:00
stoppedrules = > 1 ,
2011-02-18 01:31:22 +01:00
tcclasses = > 1 ,
tcclear = > 1 ,
tcdevices = > 1 ,
tcfilters = > 1 ,
tcinterfaces = > 1 ,
tcpri = > 1 ,
tcrules = > 1 ,
tos = > 1 ,
tunnels = > 1 ,
zones = > 1 ) ;
2009-02-22 18:30:14 +01:00
#
2011-05-19 06:25:57 +02:00
# Options that involve the the AUDIT target
#
2011-05-19 21:06:43 +02:00
our @ auditoptions = qw( BLACKLIST_DISPOSITION MACLIST_DISPOSITION TCP_FLAGS_DISPOSITION ) ;
2011-05-19 06:25:57 +02:00
#
2009-02-22 18:30:14 +01:00
# Directories to search for configuration files
#
2012-12-23 22:16:54 +01:00
our @ config_path ;
2009-02-22 18:30:14 +01:00
#
# Stash away file references here when we encounter INCLUDE
#
2012-12-23 22:16:54 +01:00
our @ includestack ;
2009-02-22 18:30:14 +01:00
#
# Allow nested opens
#
2012-12-23 22:16:54 +01:00
our @ openstack ;
2010-11-07 01:04:17 +01:00
#
# From the params file
#
2012-12-23 22:16:54 +01:00
our % params ;
2010-12-25 23:48:14 +01:00
#
2011-01-09 22:12:36 +01:00
# Entries that the compiler adds to %params
#
2012-12-23 22:16:54 +01:00
our % compiler_params ;
2011-01-09 22:12:36 +01:00
#
2010-12-25 23:48:14 +01:00
# Action parameters
#
2012-12-12 22:13:17 +01:00
our % actparms ;
2013-01-19 19:52:11 +01:00
our $ parmsmodified ;
2013-04-09 02:30:00 +02:00
our $ inline_matches ;
2009-02-22 18:30:14 +01:00
2011-05-14 22:21:31 +02:00
our $ currentline ; # Current config file line image
2012-12-23 22:16:54 +01:00
our $ currentfile ; # File handle reference
2011-12-28 19:29:15 +01:00
our $ currentfilename ; # File NAME
2012-12-23 22:16:54 +01:00
our $ currentlinenumber ; # Line number
our $ perlscript ; # File Handle Reference to current temporary file being written by an in-line Perl script
our $ perlscriptname ; # Name of that file.
our $ embedded ; # True if we're in an embedded perl script
our @ tempfiles ; # Files that need unlinking at END
our $ first_entry ; # Message to output or function to call on first non-blank line of a file
2012-12-22 00:14:23 +01:00
our $ file_format ; # Format of configuration file.
2012-12-23 22:16:54 +01:00
our $ max_format ; # Max format value
2012-12-22 22:51:24 +01:00
our $ comment ; # Current COMMENT
2012-12-26 19:55:13 +01:00
our $ comments_allowed ; # True if [?]COMMENT is allowed in the current file
our $ nocomment ; # When true, ignore [?]COMMENT in the current file
our $ warningcount ; # Used to suppress duplicate warnings about missing COMMENT support
2013-12-15 20:23:20 +01:00
our $ checkinline ; # The -i option to check/compile/etc.
2014-02-17 21:50:59 +01:00
our $ directive_callback ; # Function to call in compiler_directive
2009-02-22 18:30:14 +01:00
2012-12-26 19:55:13 +01:00
our $ shorewall_dir ; # Shorewall Directory; if non-empty, search here first for files.
2009-02-22 18:30:14 +01:00
2011-05-24 19:21:49 +02:00
our $ debug ; # Global debugging flag
2012-12-23 22:16:54 +01:00
our $ confess ; # If true, use Carp to report errors with stack trace.
2009-02-22 18:30:14 +01:00
2011-05-14 22:21:31 +02:00
our $ family ; # Protocol family (4 or 6)
2011-05-14 23:18:22 +02:00
our $ toolname ; # Name of the tool to use (iptables or iptables6)
2012-12-23 22:16:54 +01:00
our $ toolNAME ; # Tool name in CAPS
2011-05-14 22:21:31 +02:00
our $ product ; # Name of product that will run the generated script
our $ Product ; # $product with initial cap.
2009-02-22 18:30:14 +01:00
2012-02-20 17:47:48 +01:00
our $ sillyname ; # Name of temporary filter chains for testing capabilities
our $ sillyname1 ;
2012-12-26 19:55:13 +01:00
our $ iptables ; # Path to iptables/ip6tables
2013-09-04 19:16:36 +02:00
our $ iptablesw ; # True of iptables supports the -w option
2012-12-26 19:55:13 +01:00
our $ tc ; # Path to tc
our $ ip ; # Path to ip
2010-01-25 19:50:49 +01:00
2012-12-26 19:55:13 +01:00
our $ shell ; # Type of shell that processed the params file
2011-09-11 00:46:26 +02:00
use constant { BASH = > 1 ,
OLDBASH = > 2 ,
ASH = > 3 } ;
2009-02-22 18:30:14 +01:00
use constant { MIN_VERBOSITY = > - 1 ,
2011-01-21 15:56:30 +01:00
MAX_VERBOSITY = > 2 ,
2009-02-22 18:30:14 +01:00
F_IPV4 = > 4 ,
F_IPV6 = > 6 ,
2011-01-21 15:51:35 +01:00
} ;
2009-02-22 18:30:14 +01:00
2012-12-23 22:16:54 +01:00
our % validlevels ; # Valid log levels.
2009-02-22 18:30:14 +01:00
2012-01-08 04:58:45 +01:00
#
# Deprecated options with their default values
#
2015-08-21 21:42:19 +02:00
our % deprecated = (
2015-10-12 20:45:58 +02:00
LEGACY_RESTART = > 'no'
2012-12-23 22:16:54 +01:00
) ;
2009-02-22 18:30:14 +01:00
#
2012-02-29 21:34:06 +01:00
# Deprecated options that are eliminated via update
#
2015-08-21 21:42:19 +02:00
our % converted = (
2015-10-12 20:45:58 +02:00
LEGACY_RESTART = > 1
2013-01-30 17:00:47 +01:00
) ;
2012-03-16 16:16:12 +01:00
#
2015-08-01 20:11:35 +02:00
# Eliminated options
#
our % eliminated = ( LOGRATE = > 1 ,
LOGBURST = > 1 ,
EXPORTPARAMS = > 1 ,
LEGACY_FASTSTART = > 1 ,
2015-08-03 19:11:52 +02:00
IPSECFILE = > 1 ,
2015-08-21 21:42:19 +02:00
WIDE_TC_MARKS = > 1 ,
HIGH_ROUTE_MARKS = > 1 ,
BLACKLISTNEWONLY = > 1 ,
2015-08-01 20:11:35 +02:00
) ;
#
2012-03-16 16:16:12 +01:00
# Variables involved in ?IF, ?ELSE ?ENDIF processing
#
2012-12-23 22:16:54 +01:00
our $ omitting ;
our @ ifstack ;
our $ ifstack ;
2012-03-24 21:05:39 +01:00
#
2012-06-28 00:15:44 +02:00
# Entries on the ifstack are a 4-tuple:
#
# [0] - Keyword (IF, ELSEIF, ELSE or ENDIF)
# [1] - True if the outermost IF evaluated to false
# [2] - True if the the last unterminated IF evaluated to false
#
2012-03-24 21:05:39 +01:00
# From .shorewallrc
#
2012-09-04 05:09:20 +02:00
our ( % shorewallrc , % shorewallrc1 ) ;
2012-04-10 22:51:25 +02:00
#
2012-04-14 17:04:28 +02:00
# read_a_line options
#
use constant { PLAIN_READ = > 0 , # No read_a_line options
EMBEDDED_ENABLED = > 1 , # Look for embedded Shell and Perl
EXPAND_VARIABLES = > 2 , # Expand Shell variables
STRIP_COMMENTS = > 4 , # Remove comments
SUPPRESS_WHITESPACE = > 8 , # Ignore blank lines
CHECK_GUNK = > 16 , # Look for unprintable characters
2012-04-24 23:52:57 +02:00
CONFIG_CONTINUATION = > 32 , # Suppress leading whitespace if
2012-04-14 17:04:28 +02:00
# continued line ends in ',' or ':'
DO_INCLUDE = > 64 , # Look for INCLUDE <filename>
2013-11-18 15:57:54 +01:00
DO_SECTION = > 128 , # Look for [?]SECTION <section>
2012-04-14 17:04:28 +02:00
NORMAL_READ = > - 1 # All options
2012-04-11 02:01:38 +02:00
} ;
2012-03-16 16:16:12 +01:00
2012-12-23 22:16:54 +01:00
our % variables ; # Symbol table for expanding shell variables
2012-12-04 02:18:21 +01:00
2013-11-18 15:57:54 +01:00
our $ section_function ; #Function Reference for handling ?section
2012-09-04 15:59:16 +02:00
sub process_shorewallrc ($$) ;
2012-12-04 17:49:25 +01:00
sub add_variables ( \ % ) ;
2012-02-29 21:34:06 +01:00
#
2009-08-20 23:32:15 +02:00
# Rather than initializing globals in an INIT block or during declaration,
2009-08-16 18:24:51 +02:00
# we initialize them in a function. This is done for two reasons:
#
2009-08-17 19:45:46 +02:00
# 1. Proper initialization depends on the address family which isn't
2009-08-16 18:24:51 +02:00
# known until the compiler has started.
#
# 2. The compiler can run multiple times in the same process so it has to be
2009-08-17 19:45:46 +02:00
# able to re-initialize its dependent modules' state.
2009-02-22 18:30:14 +01:00
#
2012-09-04 00:07:50 +02:00
sub initialize ( $;$$) {
( $ family , my ( $ shorewallrc , $ shorewallrc1 ) ) = @ _ ;
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
( $ product , $ Product , $ toolname , $ toolNAME ) = qw( shorewall Shorewall iptables IPTABLES ) ;
} else {
( $ product , $ Product , $ toolname , $ toolNAME ) = qw( shorewall6 Shorewall6 ip6tables IP6TABLES ) ;
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
2011-01-16 05:59:59 +01:00
$ verbosity = 0 ; # Verbosity setting. -1 = silent, 0 = almost silent, 1 = major progress messages only, 2 = all progress messages (very noisy)
$ log = undef ; # File reference for log file
$ log_verbosity = - 1 ; # Verbosity of log.
$ timestamp = '' ; # If true, we are to timestamp each progress message
$ script = 0 ; # Script (output) file Handle Reference
2009-10-06 00:43:29 +02:00
$ script_enabled = 0 ; # Writing to output file is disabled initially
2011-01-16 05:59:59 +01:00
$ lastlineblank = 0 ; # Avoid extra blank lines in the output
$ indent1 = '' ; # Current indentation tabs
$ indent2 = '' ; # Current indentation spaces
$ indent = '' ; # Current total indentation
2009-10-06 00:43:29 +02:00
( $ dir , $ file ) = ( '' , '' ) ; # Script's Directory and Filename
2011-01-16 05:59:59 +01:00
$ tempfile = '' ; # Temporary File Name
2012-04-24 23:52:57 +02:00
$ sillyname =
2011-01-16 05:59:59 +01:00
$ sillyname1 = '' ; # Temporary ipchains
2012-03-16 16:16:12 +01:00
$ omitting = 0 ;
$ ifstack = 0 ;
@ ifstack = ( ) ;
2012-05-16 01:38:56 +02:00
$ embedded = 0 ;
2014-02-17 21:50:59 +01:00
$ directive_callback
= 0 ;
2009-02-22 18:30:14 +01:00
#
2012-12-22 22:51:24 +01:00
# Contents of last COMMENT line.
#
2012-12-23 19:50:31 +01:00
$ comment = '' ;
$ warningcount = 0 ;
2012-12-22 22:51:24 +01:00
#
2009-02-22 18:30:14 +01:00
# Misc Globals
#
2013-02-09 18:32:12 +01:00
% globals = ( SHAREDIRPL = > '' ,
CONFIGDIR = > '' , # Compile-time configuration directory (location of $product.conf)
ESTABLISHED_DISPOSITION = > 'ACCEPT' ,
LOGPARMS = > '' ,
TC_SCRIPT = > '' ,
EXPORT = > 0 ,
KLUDGEFREE = > '' ,
2015-10-12 23:08:24 +02:00
VERSION = > "5.0.1" ,
2015-04-01 00:53:05 +02:00
CAPVERSION = > 40609 ,
2015-09-07 01:08:59 +02:00
BLACKLIST_LOG_TAG = > '' ,
RELATED_LOG_TAG = > '' ,
MACLIST_LOG_TAG = > '' ,
TCP_FLAGS_LOG_TAG = > '' ,
SMURF_LOG_TAG = > '' ,
RPFILTER_LOG_TAG = > '' ,
INVALID_LOG_TAG = > '' ,
UNTRACKED_LOG_TAG = > '' ,
2009-02-22 18:30:14 +01:00
) ;
#
# From shorewall.conf file
#
2011-01-16 04:20:24 +01:00
% config =
( STARTUP_ENABLED = > undef ,
VERBOSITY = > undef ,
#
# Logging
#
LOGFILE = > undef ,
LOGFORMAT = > undef ,
LOGTAGONLY = > undef ,
LOGLIMIT = > undef ,
2015-08-21 21:42:19 +02:00
LOGRATE = > undef ,
LOGBURST = > undef ,
2011-01-16 04:20:24 +01:00
LOGALLNEW = > undef ,
2013-02-12 16:47:02 +01:00
BLACKLIST_LOG_LEVEL = > undef ,
2011-12-06 01:08:17 +01:00
RELATED_LOG_LEVEL = > undef ,
2011-01-16 04:20:24 +01:00
RFC1918_LOG_LEVEL = > undef ,
MACLIST_LOG_LEVEL = > undef ,
TCP_FLAGS_LOG_LEVEL = > undef ,
SMURF_LOG_LEVEL = > undef ,
LOG_MARTIANS = > undef ,
LOG_VERBOSITY = > undef ,
STARTUP_LOG = > undef ,
2011-05-28 04:42:09 +02:00
SFILTER_LOG_LEVEL = > undef ,
2012-07-15 19:05:32 +02:00
RPFILTER_LOG_LEVEL = > undef ,
2013-01-25 00:42:01 +01:00
INVALID_LOG_LEVEL = > undef ,
UNTRACKED_LOG_LEVEL = > undef ,
2014-09-25 00:26:13 +02:00
LOG_BACKEND = > undef ,
2011-01-16 04:20:24 +01:00
#
# Location of Files
#
IP = > undef ,
TC = > undef ,
IPSET = > undef ,
PERL = > undef ,
PATH = > undef ,
SHOREWALL_SHELL = > undef ,
SUBSYSLOCK = > undef ,
MODULESDIR = > undef ,
CONFIG_PATH = > undef ,
RESTOREFILE = > undef ,
LOCKFILE = > undef ,
2012-05-20 17:59:59 +02:00
GEOIPDIR = > undef ,
2012-07-28 20:21:16 +02:00
NFACCT = > undef ,
2011-01-16 04:20:24 +01:00
#
# Default Actions/Macros
#
DROP_DEFAULT = > undef ,
REJECT_DEFAULT = > undef ,
ACCEPT_DEFAULT = > undef ,
QUEUE_DEFAULT = > undef ,
NFQUEUE_DEFAULT = > undef ,
#
# RSH/RCP Commands
#
RSH_COMMAND = > undef ,
RCP_COMMAND = > undef ,
#
# Firewall Options
#
BRIDGING = > undef ,
IP_FORWARDING = > undef ,
ADD_IP_ALIASES = > undef ,
ADD_SNAT_ALIASES = > undef ,
RETAIN_ALIASES = > undef ,
TC_ENABLED = > undef ,
TC_EXPERT = > undef ,
TC_PRIOMAP = > undef ,
CLEAR_TC = > undef ,
MARK_IN_FORWARD_CHAIN = > undef ,
CLAMPMSS = > undef ,
ROUTE_FILTER = > undef ,
DETECT_DNAT_IPADDRS = > undef ,
MUTEX_TIMEOUT = > undef ,
ADMINISABSENTMINDED = > undef ,
2013-01-30 17:00:47 +01:00
BLACKLIST = > undef ,
2011-01-16 04:20:24 +01:00
BLACKLISTNEWONLY = > undef ,
DELAYBLACKLISTLOAD = > undef ,
MODULE_SUFFIX = > undef ,
DISABLE_IPV6 = > undef ,
DYNAMIC_ZONES = > undef ,
PKTTYPE = > undef ,
MACLIST_TABLE = > undef ,
MACLIST_TTL = > undef ,
SAVE_IPSETS = > undef ,
2013-01-04 18:17:57 +01:00
SAVE_ARPTABLES = > undef ,
2011-01-16 04:20:24 +01:00
MAPOLDACTIONS = > undef ,
FASTACCEPT = > undef ,
IMPLICIT_CONTINUE = > undef ,
2012-03-18 21:36:23 +01:00
IPSET_WARNINGS = > undef ,
2011-01-16 04:20:24 +01:00
HIGH_ROUTE_MARKS = > undef ,
USE_ACTIONS = > undef ,
OPTIMIZE = > undef ,
SHOREWALL_COMPILER = > undef ,
EXPAND_POLICIES = > undef ,
KEEP_RT_TABLES = > undef ,
DELETE_THEN_ADD = > undef ,
MULTICAST = > undef ,
DONT_LOAD = > '' ,
2012-08-02 20:06:41 +02:00
AUTOCOMMENT = > undef ,
2011-01-16 04:20:24 +01:00
MANGLE_ENABLED = > undef ,
RFC1918_STRICT = > undef ,
NULL_ROUTE_RFC1918 = > undef ,
USE_DEFAULT_RT = > undef ,
RESTORE_DEFAULT_ROUTE = > undef ,
FAST_STOP = > undef ,
AUTOMAKE = > undef ,
WIDE_TC_MARKS = > undef ,
TRACK_PROVIDERS = > undef ,
ZONE2ZONE = > undef ,
ACCOUNTING = > undef ,
OPTIMIZE_ACCOUNTING = > undef ,
2011-05-17 21:51:33 +02:00
ACCOUNTING_TABLE = > undef ,
2011-01-16 04:20:24 +01:00
DYNAMIC_BLACKLIST = > undef ,
LOAD_HELPERS_ONLY = > undef ,
REQUIRE_INTERFACE = > undef ,
FORWARD_CLEAR_MARK = > undef ,
COMPLETE = > undef ,
2011-02-06 17:42:35 +01:00
EXPORTMODULES = > undef ,
2011-12-21 01:03:56 +01:00
USE_PHYSICAL_NAMES = > undef ,
2012-08-03 19:53:20 +02:00
HELPERS = > undef ,
2012-08-12 16:25:11 +02:00
AUTOHELPERS = > undef ,
2012-10-11 16:34:57 +02:00
RESTORE_ROUTEMARKS = > undef ,
2012-12-12 20:51:31 +01:00
IGNOREUNKNOWNVARIABLES = > undef ,
2012-12-27 18:58:45 +01:00
WARNOLDCAPVERSION = > undef ,
2013-01-13 22:23:38 +01:00
DEFER_DNS_RESOLUTION = > undef ,
2013-03-24 18:56:38 +01:00
USE_RT_NAMES = > undef ,
2013-04-21 16:30:31 +02:00
CHAIN_SCRIPTS = > undef ,
2013-07-24 16:22:51 +02:00
TRACK_RULES = > undef ,
2013-09-01 18:14:10 +02:00
REJECT_ACTION = > undef ,
2013-12-14 22:35:01 +01:00
INLINE_MATCHES = > undef ,
2014-02-05 01:34:03 +01:00
BASIC_FILTERS = > undef ,
2015-06-01 21:59:25 +02:00
WORKAROUNDS = > undef ,
2015-07-27 18:19:52 +02:00
LEGACY_RESTART = > undef ,
2015-10-12 20:45:58 +02:00
RESTART = > undef ,
2011-01-16 04:20:24 +01:00
#
# Packet Disposition
#
MACLIST_DISPOSITION = > undef ,
TCP_FLAGS_DISPOSITION = > undef ,
BLACKLIST_DISPOSITION = > undef ,
2011-05-22 00:02:04 +02:00
SMURF_DISPOSITION = > undef ,
2011-05-28 04:42:09 +02:00
SFILTER_DISPOSITION = > undef ,
2012-07-15 19:05:32 +02:00
RPFILTER_DISPOSITION = > undef ,
2011-12-06 01:08:17 +01:00
RELATED_DISPOSITION = > undef ,
2013-01-24 17:33:59 +01:00
INVALID_DISPOSITION = > undef ,
2013-01-25 00:42:01 +01:00
UNTRACKED_DISPOSITION = > undef ,
2011-01-16 04:20:24 +01:00
#
# Mark Geometry
#
TC_BITS = > undef ,
PROVIDER_BITS = > undef ,
PROVIDER_OFFSET = > undef ,
2011-11-17 19:40:47 +01:00
MASK_BITS = > undef ,
ZONE_BITS = > undef ,
2011-01-16 04:20:24 +01:00
) ;
2011-07-19 20:57:12 +02:00
#
# Valid log levels
#
2011-01-16 04:20:24 +01:00
% validlevels = ( DEBUG = > 7 ,
INFO = > 6 ,
NOTICE = > 5 ,
WARNING = > 4 ,
WARN = > 4 ,
ERR = > 3 ,
ERROR = > 3 ,
CRIT = > 2 ,
ALERT = > 1 ,
EMERG = > 0 ,
PANIC = > 0 ,
NONE = > '' ,
NFLOG = > 'NFLOG' ,
2011-11-17 16:22:07 +01:00
LOGMARK = > 'LOGMARK' ,
2011-07-19 20:57:12 +02:00
) ;
2009-02-22 18:30:14 +01:00
#
2010-01-25 16:56:16 +01:00
# From parsing the capabilities file or capabilities detection
2009-02-22 18:30:14 +01:00
#
% capabilities =
( NAT_ENABLED = > undef ,
MANGLE_ENABLED = > undef ,
MULTIPORT = > undef ,
XMULTIPORT = > undef ,
2013-03-10 17:04:47 +01:00
EMULTIPORT = > undef ,
2009-02-22 18:30:14 +01:00
CONNTRACK_MATCH = > undef ,
NEW_CONNTRACK_MATCH = > undef ,
OLD_CONNTRACK_MATCH = > undef ,
USEPKTTYPE = > undef ,
POLICY_MATCH = > undef ,
PHYSDEV_MATCH = > undef ,
PHYSDEV_BRIDGE = > undef ,
LENGTH_MATCH = > undef ,
IPRANGE_MATCH = > undef ,
RECENT_MATCH = > undef ,
OWNER_MATCH = > undef ,
2012-03-26 05:18:20 +02:00
OWNER_NAME_MATCH = > undef ,
2009-02-22 18:30:14 +01:00
IPSET_MATCH = > undef ,
2010-08-04 06:06:17 +02:00
OLD_IPSET_MATCH = > undef ,
2014-01-02 18:36:35 +01:00
IPSET_MATCH_NOMATCH = > undef ,
IPSET_MATCH_COUNTERS = > undef ,
2011-06-23 15:36:35 +02:00
IPSET_V5 = > undef ,
2009-02-22 18:30:14 +01:00
CONNMARK = > undef ,
XCONNMARK = > undef ,
CONNMARK_MATCH = > undef ,
XCONNMARK_MATCH = > undef ,
RAW_TABLE = > undef ,
2011-08-13 20:14:29 +02:00
RAWPOST_TABLE = > undef ,
2009-02-22 18:30:14 +01:00
IPP2P_MATCH = > undef ,
OLD_IPP2P_MATCH = > undef ,
CLASSIFY_TARGET = > undef ,
ENHANCED_REJECT = > undef ,
KLUDGEFREE = > undef ,
MARK = > undef ,
XMARK = > undef ,
2010-01-13 02:01:20 +01:00
EXMARK = > undef ,
2009-02-22 18:30:14 +01:00
MANGLE_FORWARD = > undef ,
COMMENTS = > undef ,
ADDRTYPE = > undef ,
TCPMSS_MATCH = > undef ,
HASHLIMIT_MATCH = > undef ,
NFQUEUE_TARGET = > undef ,
REALM_MATCH = > undef ,
HELPER_MATCH = > undef ,
CONNLIMIT_MATCH = > undef ,
TIME_MATCH = > undef ,
GOTO_TARGET = > undef ,
2011-07-16 18:41:53 +02:00
LOG_TARGET = > 1 , # Assume that we have it.
2011-11-12 23:10:48 +01:00
ULOG_TARGET = > undef ,
NFLOG_TARGET = > undef ,
2009-04-12 17:22:19 +02:00
LOGMARK_TARGET = > undef ,
2009-04-19 17:46:57 +02:00
IPMARK_TARGET = > undef ,
2010-01-17 17:15:14 +01:00
TPROXY_TARGET = > undef ,
2009-08-15 17:35:54 +02:00
PERSISTENT_SNAT = > undef ,
2009-09-23 22:56:31 +02:00
OLD_HL_MATCH = > undef ,
2010-02-12 01:22:47 +01:00
FLOW_FILTER = > undef ,
2010-07-04 18:08:04 +02:00
FWMARK_RT_MASK = > undef ,
2010-08-27 17:35:33 +02:00
MARK_ANYWHERE = > undef ,
2010-11-27 01:41:07 +01:00
HEADER_MATCH = > undef ,
2011-05-20 16:47:35 +02:00
ACCOUNT_TARGET = > undef ,
AUDIT_TARGET = > undef ,
2011-09-22 00:20:50 +02:00
CONDITION_MATCH = > undef ,
2011-10-01 22:54:52 +02:00
IPTABLES_S = > undef ,
2011-11-01 14:34:57 +01:00
BASIC_FILTER = > undef ,
2014-01-03 18:35:34 +01:00
BASIC_EMATCH = > undef ,
2011-12-04 23:35:53 +01:00
CT_TARGET = > undef ,
2012-01-06 01:49:26 +01:00
STATISTIC_MATCH = > undef ,
2012-02-02 21:54:00 +01:00
IMQ_TARGET = > undef ,
2012-02-20 17:47:48 +01:00
DSCP_MATCH = > undef ,
DSCP_TARGET = > undef ,
2012-05-15 02:12:46 +02:00
GEOIP_MATCH = > undef ,
2012-07-15 16:54:46 +02:00
RPFILTER_MATCH = > undef ,
2012-07-28 17:19:05 +02:00
NFACCT_MATCH = > undef ,
2012-10-23 00:42:13 +02:00
CHECKSUM_TARGET = > undef ,
2013-01-04 18:17:57 +01:00
ARPTABLESJF = > undef ,
2013-02-27 18:25:26 +01:00
MASQUERADE_TGT = > undef ,
2013-03-10 18:07:52 +01:00
UDPLITEREDIRECT = > undef ,
2013-04-09 23:04:16 +02:00
NEW_TOS_MATCH = > undef ,
2013-10-07 16:54:52 +02:00
REAP_OPTION = > undef ,
2014-12-29 00:23:30 +01:00
TARPIT_TARGET = > undef ,
2015-01-02 18:05:06 +01:00
IFACE_MATCH = > undef ,
2015-04-01 00:53:05 +02:00
TCPMSS_TARGET = > undef ,
2012-10-23 00:42:13 +02:00
2012-08-03 00:38:23 +02:00
AMANDA_HELPER = > undef ,
FTP_HELPER = > undef ,
2012-08-07 00:54:45 +02:00
FTP0_HELPER = > undef ,
2012-08-03 19:53:20 +02:00
H323_HELPER = > undef ,
2012-08-03 00:38:23 +02:00
IRC_HELPER = > undef ,
2012-08-07 00:54:45 +02:00
IRC0_HELPER = > undef ,
2012-08-03 00:38:23 +02:00
NETBIOS_NS_HELPER = > undef ,
PPTP_HELPER = > undef ,
SANE_HELPER = > undef ,
2012-08-07 00:54:45 +02:00
SANE0_HELPER = > undef ,
2012-08-03 00:38:23 +02:00
SIP_HELPER = > undef ,
2012-08-07 00:54:45 +02:00
SIP0_HELPER = > undef ,
2012-08-03 00:38:23 +02:00
SNMP_HELPER = > undef ,
TFTP_HELPER = > undef ,
2012-08-07 00:54:45 +02:00
TFTP0_HELPER = > undef ,
2012-08-03 00:38:23 +02:00
2009-02-22 18:30:14 +01:00
CAPVERSION = > undef ,
2012-06-02 23:06:31 +02:00
LOG_OPTIONS = > 1 ,
2009-12-21 00:54:41 +01:00
KERNELVERSION = > undef ,
2009-02-22 18:30:14 +01:00
) ;
#
# Directories to search for configuration files
#
@ config_path = ( ) ;
#
# Stash away file references here when we encounter INCLUDE
#
@ includestack = ( ) ;
#
# Allow nested opens
#
@ openstack = ( ) ;
$ currentline = '' ; # Line image
$ currentfile = undef ; # File handle reference
$ currentfilename = '' ; # File NAME
$ currentlinenumber = 0 ; # Line number
$ first_entry = 0 ; # Message to output or function to call on first non-blank file entry
2012-12-22 00:23:26 +01:00
$ max_format = 1 ;
2012-12-23 19:49:32 +01:00
$ comments_allowed = 0 ;
2012-12-24 19:11:53 +01:00
$ nocomment = 0 ;
2009-02-22 18:30:14 +01:00
$ shorewall_dir = '' ; #Shorewall Directory
$ debug = 0 ;
2011-05-24 19:21:49 +02:00
$ confess = 0 ;
2012-04-24 23:52:57 +02:00
2011-06-26 16:45:09 +02:00
% params = ( ) ;
2010-12-25 23:48:14 +01:00
2011-01-09 22:12:36 +01:00
% compiler_params = ( ) ;
2013-01-20 16:32:34 +01:00
% actparms = ( 0 = > 0 , loglevel = > '' , logtag = > '' , chain = > '' , disposition = > '' , caller = > '' ) ;
2013-01-19 19:52:11 +01:00
$ parmsmodified = 0 ;
2011-01-16 04:20:24 +01:00
2012-08-03 19:53:20 +02:00
% helpers_enabled = (
amanda = > 1 ,
ftp = > 1 ,
2012-08-07 00:54:45 +02:00
'ftp-0' = > 1 ,
2012-08-03 19:53:20 +02:00
h323 = > 1 ,
irc = > 1 ,
2012-08-07 00:54:45 +02:00
'irc-0' = > 1 ,
2012-08-03 19:53:20 +02:00
'netbios-ns' = > 1 ,
pptp = > 1 ,
sane = > 1 ,
2012-08-07 00:54:45 +02:00
'sane-0' = > 1 ,
2012-08-03 19:53:20 +02:00
sip = > 1 ,
2012-08-07 00:54:45 +02:00
'sip-0' = > 1 ,
2012-08-03 19:53:20 +02:00
snmp = > 1 ,
tftp = > 1 ,
2012-08-07 00:54:45 +02:00
'tftp-0' = > 1 ,
2012-08-03 19:53:20 +02:00
) ;
2012-08-07 00:54:45 +02:00
% helpers_map = ( amanda = > 'AMANDA_HELPER' ,
ftp = > 'FTP_HELPER' ,
irc = > 'IRC_HELPER' ,
'netbios-ns' = > 'NETBIOS_NS_HELPER' ,
pptp = > 'PPTP_HELPER' ,
'Q.931' = > 'H323_HELPER' ,
RAS = > 'H323_HELPER' ,
sane = > 'SANE_HELPER' ,
sip = > 'SIP_HELPER' ,
snmp = > 'SNMP_HELPER' ,
tftp = > 'TFTP_HELPER' ,
) ;
% helpers_aliases = ( amanda = > 'amanda' ,
ftp = > 'ftp' ,
irc = > 'irc' ,
'netbios-ns' = > 'netbios-ns' ,
pptp = > 'pptp' ,
'Q.931' = > 'Q.931' ,
RAS = > 'RAS' ,
sane = > 'sane' ,
sip = > 'sip' ,
snmp = > 'snmp' ,
tftp = > 'tftp' ,
) ;
2012-09-04 15:59:16 +02:00
% shorewallrc = (
SHAREDIR = > '/usr/share/' ,
CONFDIR = > '/etc/' ,
) ;
2012-12-04 02:18:21 +01:00
2012-12-04 17:49:25 +01:00
% variables = % ENV ;
2012-09-04 15:59:16 +02:00
#
# If we are compiling for export, process the shorewallrc from the remote system
#
if ( $ shorewallrc1 ) {
process_shorewallrc ( $ shorewallrc1 ,
$ family == F_IPV4 ? 'shorewall-lite' : 'shorewall6-lite'
) ;
% shorewallrc1 = % shorewallrc ;
% shorewallrc = (
SHAREDIR = > '/usr/share/' ,
CONFDIR = > '/etc/' ,
) ;
}
2012-09-03 18:50:07 +02:00
#
# Process the global shorewallrc file
#
2012-09-04 00:07:50 +02:00
# Note: The build file executes this function passing only the protocol family
#
2012-09-04 15:59:16 +02:00
process_shorewallrc ( $ shorewallrc ,
$ family == F_IPV4 ? 'shorewall' : 'shorewall6'
) if defined $ shorewallrc ;
2012-05-08 01:55:17 +02:00
2014-09-28 20:19:41 +02:00
$ globals { SHAREDIRPL } = "$shorewallrc{SHAREDIR}/shorewall/" ;
$ globals { SAVED_IPSETS } = [] ;
2012-05-08 01:55:17 +02:00
if ( $ family == F_IPV4 ) {
$ globals { SHAREDIR } = "$shorewallrc{SHAREDIR}/shorewall" ;
$ globals { PRODUCT } = 'shorewall' ;
$ config { IPTABLES } = undef ;
2013-01-04 18:17:57 +01:00
$ config { ARPTABLES } = undef ;
2012-05-08 01:55:17 +02:00
$ validlevels { ULOG } = 'ULOG' ;
} else {
$ globals { SHAREDIR } = "$shorewallrc{SHAREDIR}/shorewall6" ;
$ globals { PRODUCT } = 'shorewall6' ;
$ config { IP6TABLES } = undef ;
2013-01-04 18:17:57 +01:00
delete $ config { ARPTABLES } ;
2011-01-16 04:20:24 +01:00
}
2012-09-04 15:59:16 +02:00
% shorewallrc1 = % shorewallrc unless $ shorewallrc1 ;
2012-12-04 02:18:21 +01:00
2012-12-04 17:49:25 +01:00
add_variables % shorewallrc1 ;
2009-02-22 18:30:14 +01:00
}
my @ abbr = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ) ;
2012-05-04 02:17:55 +02:00
#
# Create 'currentlineinfo'
#
sub currentlineinfo () {
2012-05-04 16:01:08 +02:00
my $ linenumber = $ currentlinenumber || 1 ;
2012-05-04 02:17:55 +02:00
if ( $ currentfile ) {
2012-05-08 17:55:24 +02:00
my $ lineinfo = " $currentfilename " ;
2012-05-04 02:17:55 +02:00
2012-05-04 16:01:08 +02:00
if ( $ linenumber eq 'EOF' ) {
2012-05-04 02:17:55 +02:00
$ lineinfo . = '(EOF)'
} else {
2012-05-04 16:01:08 +02:00
$ lineinfo . = "(line $linenumber)" ;
}
#
# Unwind the current include stack
#
for ( my $ i = @ includestack - 1 ; $ i >= 0 ; $ i - - ) {
my $ info = $ includestack [ $ i ] ;
$ linenumber = $ info - > [ 2 ] || 1 ;
$ lineinfo . = "\n from $info->[1] (line $linenumber)" ;
}
#
# Now unwind the open stack; each element is an include stack
#
for ( my $ i = @ openstack - 1 ; $ i >= 0 ; $ i - - ) {
my $ istack = $ openstack [ $ i ] ;
for ( my $ j = ( @$ istack - 1 ) ; $ j >= 0 ; $ j - - ) {
my $ info = $ istack - > [ $ j ] ;
$ linenumber = $ info - > [ 2 ] || 1 ;
$ lineinfo . = "\n from $info->[1] (line $linenumber)" ;
2012-05-04 02:17:55 +02:00
}
}
$ lineinfo ;
} else {
'' ;
}
}
2013-07-24 16:22:51 +02:00
sub shortlineinfo ( $ ) {
if ( $ config { TRACK_RULES } ) {
if ( $ currentfile ) {
my $ comment = '@@@ ' . join ( ':' , $ currentfilename , $ currentlinenumber ) . ' @@@' ;
$ comment = '@@@ ' . join ( ':' , basename ( $ currentfilename ) , $ currentlinenumber ) . ' @@@' if length $ comment > 255 ;
$ comment = '@@@ Filename Too Long @@@' if length $ comment > 255 ;
$ comment ;
} else {
#
# Alternate lineinfo may have been passed
#
$ _ [ 0 ] || ''
}
}
}
2013-01-26 16:30:50 +01:00
sub handle_first_entry () ;
2009-02-22 18:30:14 +01:00
#
# Issue a Warning Message
#
sub warning_message
{
2012-05-04 02:17:55 +02:00
my $ currentlineinfo = currentlineinfo ;
2009-02-22 18:30:14 +01:00
our @ localtime ;
2013-01-26 16:30:50 +01:00
handle_first_entry if $ first_entry ;
2009-08-31 19:41:08 +02:00
$| = 1 ; #Reset output buffering (flush any partially filled buffers).
2009-02-22 18:30:14 +01:00
if ( $ log ) {
@ localtime = localtime ;
printf $ log '%s %2d %02d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
}
2011-05-24 19:21:49 +02:00
if ( $ confess ) {
2009-02-22 18:30:14 +01:00
print STDERR longmess ( " WARNING: @_$currentlineinfo" ) ;
print $ log longmess ( " WARNING: @_$currentlineinfo\n" ) if $ log ;
} else {
print STDERR " WARNING: @_$currentlineinfo\n" ;
print $ log " WARNING: @_$currentlineinfo\n" if $ log ;
}
2009-08-31 19:41:08 +02:00
$| = 0 ; #Re-allow output buffering
2009-02-22 18:30:14 +01:00
}
2013-06-24 22:07:38 +02:00
#
# Q[uie]t version of system(). Returns true for success
#
sub qt ( $ ) {
if ( $ debug ) {
print "SYS----> @_\n" ;
system ( "@_ 2>&1 < /dev/null" ) == 0 ;
} else {
system ( "@_ > /dev/null 2>&1 < /dev/null" ) == 0 ;
}
}
sub qt0 ( $ ) {
if ( $ debug ) {
print "SYS----> @_\n" ;
system ( "@_ 2>&1 < /dev/null" ) ;
} else {
system ( "@_ > /dev/null 2>&1 < /dev/null" ) ;
}
}
sub qt1 ( $ ) {
1 while qt0 ( "@_" ) == 4 ;
$? == 0 ;
}
2013-05-01 23:48:27 +02:00
#
# Delete the test chains
#
sub cleanup_iptables () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -X $sillyname" ) ;
qt1 ( "$iptables $iptablesw -F $sillyname1" ) ;
qt1 ( "$iptables $iptablesw -X $sillyname1" ) ;
2013-05-01 23:48:27 +02:00
if ( $ capabilities { MANGLE_ENABLED } ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t mangle -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t mangle -X $sillyname" ) ;
2013-05-01 23:48:27 +02:00
}
if ( $ capabilities { NAT_ENABLED } ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t nat -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t nat -X $sillyname" ) ;
2013-05-01 23:48:27 +02:00
}
if ( $ capabilities { RAW_TABLE } ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t raw -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t raw -X $sillyname" ) ;
2013-05-01 23:48:27 +02:00
}
2014-12-24 00:25:20 +01:00
$ sillyname = $ sillyname1 = '' ;
2013-05-01 23:48:27 +02:00
}
#
# Clean up after the compiler exits
#
2009-08-26 19:34:04 +02:00
sub cleanup () {
#
# Close files first in case we're running under Cygwin
#
2009-10-06 00:43:29 +02:00
close $ script , $ script = undef if $ script ;
close $ perlscript , $ perlscript = undef if $ perlscript ;
2009-08-30 17:05:10 +02:00
close $ log , $ log = undef if $ log ;
2012-05-08 17:58:14 +02:00
if ( $ currentfile ) {
#
# We have a current input file; close it
#
close $ currentfile ;
#
# Unwind the current include stack
#
for ( my $ i = @ includestack - 1 ; $ i >= 0 ; $ i - - ) {
my $ info = $ includestack [ $ i ] ;
close $ info - > [ 0 ] ;
}
#
# Now unwind the open stack; each element is an include stack
#
for ( my $ i = @ openstack - 1 ; $ i >= 0 ; $ i - - ) {
my $ istack = $ openstack [ $ i ] ;
for ( my $ j = ( @$ istack - 1 ) ; $ j >= 0 ; $ j - - ) {
2013-01-12 00:50:23 +01:00
my $ info = $ istack - > [ $ j ] [ 0 ] ;
close $ info if $ info ;
2012-05-08 17:58:14 +02:00
}
}
}
2009-08-26 19:34:04 +02:00
#
# Unlink temporary files
#
2009-08-31 18:08:49 +02:00
unlink ( $ tempfile ) , $ tempfile = undef if $ tempfile ;
2009-10-06 00:43:29 +02:00
unlink ( $ perlscriptname ) , $ perlscriptname = undef if $ perlscriptname ;
2009-08-31 18:08:49 +02:00
unlink ( @ tempfiles ) , @ tempfiles = ( ) if @ tempfiles ;
2010-01-25 19:50:49 +01:00
#
2010-01-26 00:59:31 +01:00
# Delete temporary chains
2010-01-25 19:50:49 +01:00
#
2013-05-01 23:48:27 +02:00
cleanup_iptables if $ sillyname ;
2009-08-26 19:34:04 +02:00
}
2009-02-22 18:30:14 +01:00
#
# Issue fatal error message and die
#
sub fatal_error {
2012-05-04 02:17:55 +02:00
my $ currentlineinfo = currentlineinfo ;
2009-02-22 18:30:14 +01:00
2013-01-26 16:30:50 +01:00
handle_first_entry if $ first_entry ;
2009-08-31 19:41:08 +02:00
$| = 1 ; #Reset output buffering (flush any partially filled buffers).
2009-02-22 18:30:14 +01:00
if ( $ log ) {
our @ localtime = localtime ;
printf $ log '%s %2d %02d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
2011-05-24 19:21:49 +02:00
if ( $ confess ) {
2012-08-29 20:35:11 +02:00
print $ log longmess ( " ERROR: @_$currentlineinfo\n" ) ;
2009-02-22 18:30:14 +01:00
} else {
2012-08-29 20:35:11 +02:00
print $ log " ERROR: @_$currentlineinfo\n" ;
2009-02-22 18:30:14 +01:00
}
close $ log ;
$ log = undef ;
}
2009-08-26 19:34:04 +02:00
cleanup ;
2012-05-16 01:44:35 +02:00
2012-05-16 01:38:56 +02:00
if ( $ embedded ) {
confess "@_$currentlineinfo" if $ confess ;
die "@_$currentlineinfo\n" ;
} else {
2012-08-29 20:35:11 +02:00
confess " ERROR: @_$currentlineinfo" if $ confess ;
die " ERROR: @_$currentlineinfo\n" ;
2012-05-16 01:38:56 +02:00
}
2009-02-22 18:30:14 +01:00
}
2011-01-09 20:31:38 +01:00
sub fatal_error1 {
2013-01-26 16:30:50 +01:00
handle_first_entry if $ first_entry ;
2009-02-22 18:30:14 +01:00
$| = 1 ;
if ( $ log ) {
our @ localtime = localtime ;
printf $ log '%s %2d %02d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
if ( $ debug ) {
2012-08-29 20:35:11 +02:00
print $ log longmess ( " ERROR: @_\n" ) ;
2009-02-22 18:30:14 +01:00
} else {
2012-08-29 20:35:11 +02:00
print $ log " ERROR: @_\n" ;
2009-02-22 18:30:14 +01:00
}
close $ log ;
$ log = undef ;
}
2009-08-26 19:34:04 +02:00
cleanup ;
2012-08-29 20:35:11 +02:00
confess " ERROR: @_" if $ debug ;
die " ERROR: @_\n" ;
2009-02-22 18:30:14 +01:00
}
2009-03-09 22:45:18 +01:00
#
2012-04-15 02:57:49 +02:00
# C/C++-like assertion checker -- the optional arguments are not used but will
# appear in the stack trace
2009-03-09 22:45:18 +01:00
#
2012-04-15 02:57:49 +02:00
sub assert ( $;@ ) {
2009-03-09 21:56:53 +01:00
unless ( $ _ [ 0 ] ) {
2009-03-09 22:45:30 +01:00
my @ caller0 = caller 0 ; # Where assert() was called
my @ caller1 = caller 1 ; # Who called assert()
2009-03-09 21:56:53 +01:00
2012-04-15 02:57:49 +02:00
$ confess = 1 ;
2009-03-09 22:45:30 +01:00
fatal_error "Internal error in $caller1[3] at $caller0[1] line $caller0[2]" ;
2009-03-09 21:56:53 +01:00
}
}
2009-02-22 18:30:14 +01:00
#
# Convert value to decimal number
#
sub numeric_value ( $ ) {
my $ mark = lc $ _ [ 0 ] ;
2009-04-21 16:08:47 +02:00
my $ negative = ( $ mark =~ s/^-// ) ;
return undef unless $ mark =~ /^(0x[a-f0-9]+|0[0-7]*|[1-9]\d*)$/ ;
no warnings ;
$ mark = ( $ mark =~ /^0/ ? oct $ mark : $ mark ) ;
2009-04-20 22:26:47 +02:00
use warnings ;
2009-04-21 16:08:47 +02:00
$ negative ? - $ mark : $ mark ;
2009-02-22 18:30:14 +01:00
}
sub numeric_value1 ( $ ) {
2009-04-20 22:26:47 +02:00
no warnings ;
2009-02-22 18:30:14 +01:00
my $ val = numeric_value $ _ [ 0 ] ;
fatal_error "Invalid Number ($_[0])" unless defined $ val ;
$ val ;
2009-04-20 22:26:47 +02:00
use warnings ;
2009-02-22 18:30:14 +01:00
}
2009-04-23 21:43:57 +02:00
sub hex_value ( $ ) {
my $ val = lc $ _ [ 0 ] ;
2009-05-06 01:23:37 +02:00
return undef unless $ val =~ /^[a-fA-F0-9]+$/ ;
2009-04-23 21:43:57 +02:00
no warnings ;
oct '0x' . $ val ;
use warnings ;
}
2011-05-02 19:07:01 +02:00
#
2011-05-03 16:43:42 +02:00
# Strip off superfluous leading zeros from a hex number
2011-05-02 19:07:01 +02:00
#
sub normalize_hex ( $ ) {
2011-05-03 02:22:06 +02:00
my $ val = lc shift ;
2011-05-02 19:07:01 +02:00
$ val =~ s/^0// while $ val =~ /^0/ && length $ val > 1 ;
$ val ;
}
2009-02-22 18:30:14 +01:00
#
# Return the argument expressed in Hex
#
sub in_hex ( $ ) {
2012-05-09 22:51:49 +02:00
my $ value = $ _ [ 0 ] ;
$ value =~ /^0x/ ? $ value : sprintf '0x%x' , $ _ [ 0 ] ;
2009-02-22 18:30:14 +01:00
}
sub in_hex2 ( $ ) {
sprintf '0x%02x' , $ _ [ 0 ] ;
}
sub in_hex3 ( $ ) {
2012-09-13 18:30:11 +02:00
sprintf '%03x' , $ _ [ 0 ] ;
2009-02-22 18:30:14 +01:00
}
sub in_hex4 ( $ ) {
sprintf '0x%04x' , $ _ [ 0 ] ;
}
sub in_hex8 ( $ ) {
sprintf '0x%08x' , $ _ [ 0 ] ;
}
2009-04-23 21:43:57 +02:00
sub in_hexp ( $ ) {
sprintf '%x' , $ _ [ 0 ] ;
}
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# Write the arguments to the script file (if any) with the current indentation.
2009-02-22 18:30:14 +01:00
#
# Replaces leading spaces with tabs as appropriate and suppresses consecutive blank lines.
#
sub emit {
2009-10-06 00:43:29 +02:00
assert ( $ script_enabled ) ;
2009-04-07 05:22:30 +02:00
2010-03-28 22:09:04 +02:00
if ( $ script || $ debug ) {
2009-02-22 18:30:14 +01:00
#
# 'compile' as opposed to 'check'
#
for ( @ _ ) {
unless ( /^\s*$/ ) {
my $ line = $ _ ; # This copy is necessary because the actual arguments are almost always read-only.
$ line =~ s/^\n// if $ lastlineblank ;
$ line =~ s/^/$indent/gm if $ indent ;
$ line =~ s/ /\t/gm ;
2010-03-28 22:09:04 +02:00
print $ script "$line\n" if $ script ;
2009-02-22 18:30:14 +01:00
$ lastlineblank = ( substr ( $ line , - 1 , 1 ) eq "\n" ) ;
2010-03-28 22:09:04 +02:00
if ( $ debug ) {
$ line =~ s/^\n// ;
2010-03-29 18:48:23 +02:00
$ line =~ s/\n/\nGS-----> /g ;
print "GS-----> $line\n" ;
2010-03-28 22:09:04 +02:00
}
2009-02-22 18:30:14 +01:00
} else {
2010-03-28 22:09:04 +02:00
unless ( $ lastlineblank ) {
print $ script "\n" if $ script ;
2010-03-29 18:48:23 +02:00
print "GS-----> \n" if $ debug ;
2010-03-28 22:09:04 +02:00
}
2009-02-22 18:30:14 +01:00
$ lastlineblank = 1 ;
}
}
}
}
2010-01-11 23:16:03 +01:00
#
2013-07-07 21:52:04 +02:00
# Version of emit() that writes to standard out unconditionally
2010-01-11 23:16:03 +01:00
#
sub emitstd {
for ( @ _ ) {
unless ( /^\s*$/ ) {
my $ line = $ _ ; # This copy is necessary because the actual arguments are almost always read-only.
$ line =~ s/^\n// if $ lastlineblank ;
$ line =~ s/^/$indent/gm if $ indent ;
$ line =~ s/ /\t/gm ;
print "$line\n" ;
$ lastlineblank = ( substr ( $ line , - 1 , 1 ) eq "\n" ) ;
} else {
print "\n" unless $ lastlineblank ;
$ lastlineblank = 1 ;
}
}
}
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# Write passed message to the script with newline but no indentation.
2009-02-22 18:30:14 +01:00
#
2012-01-16 04:23:44 +01:00
sub emit_unindented ( $;$ ) {
2009-10-06 00:43:29 +02:00
assert ( $ script_enabled ) ;
2009-04-07 05:22:30 +02:00
2012-01-16 04:23:44 +01:00
print $ script $ _ [ 1 ] ? "$_[0]" : "$_[0]\n" if $ script ;
2009-02-22 18:30:14 +01:00
}
#
# Write a progress_message2 command with surrounding blank lines to the output file.
#
sub save_progress_message ( $ ) {
2009-10-06 00:43:29 +02:00
emit "\nprogress_message2 @_\n" if $ script ;
2009-02-22 18:30:14 +01:00
}
#
# Write a progress_message command to the output file.
#
sub save_progress_message_short ( $ ) {
2009-10-06 00:43:29 +02:00
emit "progress_message $_[0]" if $ script ;
2009-02-22 18:30:14 +01:00
}
#
# Set $timestamp
#
sub set_timestamp ( $ ) {
$ timestamp = shift ;
}
#
2009-08-22 16:57:55 +02:00
# Set $verbosity
2009-02-22 18:30:14 +01:00
#
2009-08-22 16:57:55 +02:00
sub set_verbosity ( $ ) {
$ verbosity = shift ;
2009-02-22 18:30:14 +01:00
}
#
2009-08-22 16:57:55 +02:00
# Set $log and $log_verbosity
2009-02-22 18:30:14 +01:00
#
sub set_log ( $$ ) {
my ( $ l , $ v ) = @ _ ;
if ( defined $ v ) {
my $ value = numeric_value ( $ v ) ;
fatal_error "Invalid Log Verbosity ( $v )" unless defined ( $ value ) && ( $ value >= - 1 ) && ( $ value <= 2 ) ;
2009-08-22 16:57:55 +02:00
$ log_verbosity = $ value ;
2009-02-22 18:30:14 +01:00
}
2009-08-22 16:57:55 +02:00
if ( $ l && $ log_verbosity >= 0 ) {
2009-02-22 18:30:14 +01:00
unless ( open $ log , '>>' , $ l ) {
2009-08-20 23:32:15 +02:00
$ log = undef ;
2009-02-22 18:30:14 +01:00
fatal_error "Unable to open STARTUP_LOG ($l) for writing: $!" ;
}
} else {
2009-08-22 16:57:55 +02:00
$ log_verbosity = - 1 ;
2009-02-22 18:30:14 +01:00
}
}
sub close_log () {
close $ log , $ log = undef if $ log ;
}
#
# Set $command, $doing and $done
#
sub set_command ( $$$ ) {
( $ command , $ doing , $ done ) = @ _ ;
}
#
# Print the current TOD to STDOUT.
#
2014-12-24 00:25:20 +01:00
sub get_localtime () {
2009-02-22 18:30:14 +01:00
our @ localtime = localtime ;
printf '%02d:%02d:%02d ' , @ localtime [ 2 , 1 , 0 ] ;
}
#
2010-03-28 22:09:04 +02:00
# Write a message if $verbosity >= 2.
2009-02-22 18:30:14 +01:00
#
sub progress_message {
my $ havelocaltime = 0 ;
2009-08-22 16:57:55 +02:00
if ( $ verbosity > 1 || $ log_verbosity > 1 ) {
2009-02-22 18:30:14 +01:00
my $ line = "@_" ;
my $ leading = $ line =~ /^(\s+)/ ? $ 1 : '' ;
$ line =~ s/\s+/ /g ;
2009-08-22 16:57:55 +02:00
if ( $ verbosity > 1 ) {
2014-12-24 00:25:20 +01:00
get_localtime , $ havelocaltime = 1 if $ timestamp ;
2009-02-22 18:30:14 +01:00
#
# We use this function to display messages containing raw config file images which may contains tabs (including multiple tabs in succession).
# The following makes such messages look more readable and uniform
#
print "${leading}${line}\n" ;
}
2009-08-22 16:57:55 +02:00
if ( $ log_verbosity > 1 ) {
2009-02-22 18:30:14 +01:00
our @ localtime ;
2009-08-20 23:32:15 +02:00
@ localtime = localtime unless $ havelocaltime ;
2009-02-22 18:30:14 +01:00
printf $ log '%s %2d %2d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
print $ log "${leading}${line}\n" ;
}
}
}
sub progress_message_nocompress {
my $ havelocaltime = 0 ;
2009-08-22 16:57:55 +02:00
if ( $ verbosity > 1 ) {
2014-12-24 00:25:20 +01:00
get_localtime , $ havelocaltime = 1 if $ timestamp ;
2009-02-22 18:30:14 +01:00
print "@_\n" ;
}
2009-08-22 16:57:55 +02:00
if ( $ log_verbosity > 1 ) {
2009-02-22 18:30:14 +01:00
our @ localtime ;
2009-08-20 23:32:15 +02:00
@ localtime = localtime unless $ havelocaltime ;
2009-02-22 18:30:14 +01:00
printf $ log '%s %2d %2d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
print $ log "@_\n" ;
}
}
#
2009-08-22 16:57:55 +02:00
# Write a message if $verbosity >= 1
2009-02-22 18:30:14 +01:00
#
sub progress_message2 {
my $ havelocaltime = 0 ;
2009-08-22 16:57:55 +02:00
if ( $ verbosity > 0 ) {
2014-12-24 00:25:20 +01:00
get_localtime , $ havelocaltime = 1 if $ timestamp ;
2009-02-22 18:30:14 +01:00
print "@_\n" ;
}
2009-08-22 16:57:55 +02:00
if ( $ log_verbosity > 0 ) {
2009-02-22 18:30:14 +01:00
our @ localtime ;
2009-08-20 23:32:15 +02:00
@ localtime = localtime unless $ havelocaltime ;
2009-02-22 18:30:14 +01:00
2010-09-23 16:15:24 +02:00
printf $ log '%s %2d %2d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
2009-02-22 18:30:14 +01:00
print $ log "@_\n" ;
}
}
#
2009-08-22 16:57:55 +02:00
# Write a message if $verbosity >= 0
2009-02-22 18:30:14 +01:00
#
sub progress_message3 {
my $ havelocaltime = 0 ;
2009-08-22 16:57:55 +02:00
if ( $ verbosity >= 0 ) {
2014-12-24 00:25:20 +01:00
get_localtime , $ havelocaltime = 1 if $ timestamp ;
2009-02-22 18:30:14 +01:00
print "@_\n" ;
}
2009-08-22 16:57:55 +02:00
if ( $ log_verbosity >= 0 ) {
2009-02-22 18:30:14 +01:00
our @ localtime ;
@ localtime = localtime unless $ havelocaltime ;
2010-09-23 16:15:24 +02:00
printf $ log '%s %2d %2d:%02d:%02d ' , $ abbr [ $ localtime [ 4 ] ] , @ localtime [ 3 , 2 , 1 , 0 ] ;
2009-02-22 18:30:14 +01:00
print $ log "@_\n" ;
}
}
#
# Push/Pop Indent
#
2012-11-30 16:49:42 +01:00
sub push_indent (;$) {
my $ times = shift || 1 ;
while ( $ times - - ) {
if ( $ indent2 ) {
$ indent2 = '' ;
$ indent = $ indent1 = $ indent1 . "\t" ;
} else {
$ indent2 = ' ' ;
$ indent = $ indent1 . $ indent2 ;
}
2009-02-22 18:30:14 +01:00
}
}
2012-11-30 16:49:42 +01:00
sub pop_indent (;$) {
my $ times = shift || 1 ;
while ( $ times - - ) {
if ( $ indent2 ) {
$ indent2 = '' ;
$ indent = $ indent1 ;
} else {
$ indent1 = substr ( $ indent1 , 0 , - 1 ) ;
$ indent2 = ' ' ;
$ indent = $ indent1 . $ indent2 ;
}
2009-02-22 18:30:14 +01:00
}
}
#
2009-10-06 00:43:29 +02:00
# Create the temporary script file -- the passed file name is the name of the final file.
2009-02-22 18:30:14 +01:00
# We create a temporary file in the same directory so that we can use rename to finalize it.
#
2009-10-06 00:43:29 +02:00
sub create_temp_script ( $$ ) {
my ( $ scriptfile , $ export ) = @ _ ;
2009-02-22 18:30:14 +01:00
my $ suffix ;
2009-10-06 00:43:29 +02:00
if ( $ scriptfile eq '-' ) {
2009-08-22 16:57:55 +02:00
$ verbosity = - 1 ;
2009-10-06 00:43:29 +02:00
$ script = undef ;
open ( $ script , '>&STDOUT' ) or fatal_error "Open of STDOUT failed" ;
2009-04-21 18:41:23 +02:00
$ file = '-' ;
return 1 ;
}
2009-02-22 18:30:14 +01:00
eval {
2009-10-06 00:43:29 +02:00
( $ file , $ dir , $ suffix ) = fileparse ( $ scriptfile ) ;
2009-02-22 18:30:14 +01:00
} ;
2009-08-26 19:34:04 +02:00
cleanup , die if $@ ;
2009-02-22 18:30:14 +01:00
fatal_error "$dir is a Symbolic Link" if - l $ dir ;
fatal_error "Directory $dir does not exist" unless - d _ ;
fatal_error "Directory $dir is not writable" unless - w _ ;
2009-10-06 00:43:29 +02:00
fatal_error "$scriptfile is a Symbolic Link" if - l $ scriptfile ;
fatal_error "$scriptfile is a Directory" if - d _ ;
fatal_error "$scriptfile exists and is not a compiled script" if - e _ && ! - x _ ;
2009-02-22 18:30:14 +01:00
fatal_error "An exported \u$globals{PRODUCT} compiled script may not be named '$globals{PRODUCT}'" if $ export && "$file" eq $ globals { PRODUCT } && $ suffix eq '' ;
eval {
$ dir = abs_path $ dir unless $ dir =~ m | ^ /|; # Work around http:/ /rt.cpan.org/ Public /Bug/ Display . html ? id = 13851
2009-10-06 00:43:29 +02:00
( $ script , $ tempfile ) = tempfile ( 'tempfileXXXX' , DIR = > $ dir ) ;
2009-02-22 18:30:14 +01:00
} ;
fatal_error "Unable to create temporary file in directory $dir" if $@ ;
$ file = "$file.$suffix" if $ suffix ;
$ dir . = '/' unless substr ( $ dir , - 1 , 1 ) eq '/' ;
$ file = $ dir . $ file ;
}
2014-12-24 00:25:20 +01:00
# Generate the SHA1 digest of the (incomplete) script
2014-10-31 02:38:45 +01:00
#
sub generate_sha1 () {
my $ data = `cat $tempfile` ;
sha1_hex $ data ;
}
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# Finalize the script file
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
sub finalize_script ( $ ) {
2009-02-22 18:30:14 +01:00
my $ export = $ _ [ 0 ] ;
2009-10-06 00:43:29 +02:00
close $ script ;
$ script = 0 ;
2009-04-21 18:41:23 +02:00
if ( $ file ne '-' ) {
2014-11-01 17:37:57 +01:00
my $ sha1sum = generate_sha1 ;
2014-11-06 17:18:52 +01:00
my $ sha1sum1 = join ( '-' , 'sha-lh' , substr ( $ sha1sum , 0 , 20 ) ) ;
my $ sha1sum2 = join ( '-' , 'sha-rh' , substr ( $ sha1sum , - 20 ) ) ;
2014-11-01 17:37:57 +01:00
@ ARGV = ( $ tempfile ) ;
$^I = '' ;
while ( < > ) {
s/g_sha1sum1=/g_sha1sum1=$sha1sum1/ ;
s/g_sha1sum2=/g_sha1sum2=$sha1sum2/ ;
print ;
2014-10-31 02:38:45 +01:00
}
2009-04-21 18:41:23 +02:00
rename $ tempfile , $ file or fatal_error "Cannot Rename $tempfile to $file: $!" ;
chmod 0700 , $ file or fatal_error "Cannot secure $file for execute access" ;
progress_message3 "Shorewall configuration compiled to $file" unless $ export ;
}
2009-02-22 18:30:14 +01:00
}
#
# Create the temporary aux config file.
#
sub create_temp_aux_config () {
eval {
2009-10-06 00:43:29 +02:00
( $ script , $ tempfile ) = tempfile ( 'tempfileXXXX' , DIR = > $ dir ) ;
2009-02-22 18:30:14 +01:00
} ;
2009-08-26 19:34:04 +02:00
cleanup , die if $@ ;
2009-02-22 18:30:14 +01:00
}
#
# Finalize the aux config file.
#
sub finalize_aux_config () {
2009-10-06 00:43:29 +02:00
close $ script ;
$ script = 0 ;
2009-02-22 18:30:14 +01:00
rename $ tempfile , "$file.conf" or fatal_error "Cannot Rename $tempfile to $file.conf: $!" ;
progress_message3 "Shorewall configuration compiled to $file" ;
}
2009-04-07 05:22:30 +02:00
#
2009-10-06 00:43:29 +02:00
# Enable writes to the script file
2009-04-07 05:22:30 +02:00
#
2009-10-06 00:43:29 +02:00
sub enable_script () {
$ script_enabled = 1 ;
2009-04-07 05:22:30 +02:00
}
#
2009-10-06 00:43:29 +02:00
# Disable writes to the script file
2009-04-07 05:22:30 +02:00
#
2009-10-06 00:43:29 +02:00
sub disable_script () {
$ script_enabled = 0 ;
2009-04-07 05:22:30 +02:00
}
2009-02-22 18:30:14 +01:00
#
# Set $config{CONFIG_PATH}
#
sub set_config_path ( $ ) {
$ config { CONFIG_PATH } = shift ;
}
#
2014-12-24 00:25:20 +01:00
# Set $debug and $confess
2009-02-22 18:30:14 +01:00
#
2011-05-24 19:21:49 +02:00
sub set_debug ( $$ ) {
$ debug = shift ;
$ confess = shift ;
$ confess || = $ debug ;
2009-02-22 18:30:14 +01:00
}
#
# Search the CONFIG_PATH for the passed file
#
sub find_file ($)
{
2011-11-08 21:59:40 +01:00
my ( $ filename , $ nosearch ) = @ _ ;
2009-02-22 18:30:14 +01:00
return $ filename if $ filename =~ '/' ;
2012-04-14 17:04:28 +02:00
for my $ directory ( @ config_path ) {
2009-02-22 18:30:14 +01:00
my $ file = "$directory$filename" ;
return $ file if - f $ file ;
}
2011-11-08 21:59:40 +01:00
"$config_path[0]$filename" ;
2009-02-22 18:30:14 +01:00
}
2015-08-31 20:21:18 +02:00
sub find_writable_file ($) {
my ( $ filename , $ nosearch ) = @ _ ;
return $ filename if $ filename =~ '/' ;
for my $ directory ( @ config_path ) {
next if $ directory =~ m | ^ $ globals { SHAREDIR } /configfiles/ ? $| || $ directory =~ m | ^ $ shorewallrc { SHAREDIR } /doc/ default - config / ? $| ;
my $ file = "$directory$filename" ;
return $ file if - f $ file && - w _ ;
}
"$config_path[0]$filename" ;
}
2014-12-24 00:25:20 +01:00
#
# Split a comma-separated list into a Perl array
#
2012-05-16 01:39:46 +02:00
sub split_list ( $$;$ ) {
my ( $ list , $ type , $ origlist ) = @ _ ;
2009-02-22 18:30:14 +01:00
2012-05-16 01:39:46 +02:00
fatal_error ( "Invalid $type list (" . ( $ origlist ? $ origlist : $ list ) . ')' ) if $ list =~ /^,|,$|,,|!,|,!$/ ;
2009-02-22 18:30:14 +01:00
split /,/ , $ list ;
}
2014-12-24 00:25:20 +01:00
#
# This version handles parenthetical list elements with embedded commas. It removes the parentheses
#
2012-12-07 00:13:14 +01:00
sub split_list1 ( $$;$ ) {
my ( $ list , $ type , $ keepparens ) = @ _ ;
2009-02-22 18:30:14 +01:00
fatal_error "Invalid $type list ($list)" if $ list =~ /^,|,$|,,|!,|,!$/ ;
my @ list1 = split /,/ , $ list ;
my @ list2 ;
my $ element = '' ;
for ( @ list1 ) {
2009-02-26 18:12:55 +01:00
my $ count ;
if ( ( $ count = tr /(/ ( / ) > 0 ) {
fatal_error "Invalid $type list ($list)" if $ element || $ count > 1 ;
2012-12-07 00:13:14 +01:00
s/\(// unless $ keepparens ;
2009-02-26 18:12:55 +01:00
if ( ( $ count = tr /)/ ) / ) > 0 ) {
fatal_error "Invalid $type list ($list)" if $ count > 1 ;
2012-12-07 00:13:14 +01:00
s/\)// unless $ keepparens ;
2009-02-26 17:53:33 +01:00
push @ list2 , $ _ ;
} else {
$ element = $ _ ;
}
2009-02-26 18:12:55 +01:00
} elsif ( ( $ count = tr /)/ ) / ) > 0 ) {
fatal_error "Invalid $type list ($list)" unless $ element && $ count == 1 ;
2012-12-07 00:13:14 +01:00
s/\)// unless $ keepparens ;
2009-02-22 18:30:14 +01:00
push @ list2 , join ',' , $ element , $ _ ;
$ element = '' ;
} elsif ( $ element ) {
$ element = join ',' , $ element , $ _ ;
} else {
push @ list2 , $ _ ;
}
}
@ list2 ;
}
2012-12-09 19:45:29 +01:00
#
# The next two functions split a list which contain arbitrarily deep paren nesting.
# The first splits on ':' and the second on ','.
#
2012-12-02 00:06:51 +01:00
sub split_list2 ( $$ ) {
my ( $ list , $ type ) = @ _ ;
fatal_error "Invalid $type ($list)" if $ list =~ /^:|::/ ;
my @ list1 = split /:/ , $ list ;
my @ list2 ;
my $ element = '' ;
my $ opencount = 0 ;
for ( @ list1 ) {
my $ count ;
if ( ( $ count = tr /(/ ( / ) > 0 ) {
$ opencount += $ count ;
if ( $ element eq '' ) {
$ element = $ _ ;
} else {
$ element = join ( ':' , $ element , $ _ ) ;
}
if ( ( $ count = tr /)/ ) / ) > 0 ) {
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
fatal_error "Invalid $type ($list)" if $ opencount < 0 ;
}
}
} elsif ( ( $ count = tr /)/ ) / ) > 0 ) {
2012-12-06 04:41:18 +01:00
fatal_error "Invalid $type ($list)" if $ element eq '' ;
2012-12-02 00:06:51 +01:00
$ element = join ( ':' , $ element , $ _ ) ;
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
fatal_error "Invalid $type ($list)" if $ opencount < 0 ;
}
} elsif ( $ element eq '' ) {
push @ list2 , $ _ ;
} else {
$ element = join ':' , $ element , $ _ ;
}
}
unless ( $ opencount == 0 ) {
fatal_error "Invalid $type ($list)" ;
}
@ list2 ;
}
2012-12-09 19:45:29 +01:00
sub split_list3 ( $$ ) {
my ( $ list , $ type ) = @ _ ;
2013-02-09 16:07:01 +01:00
#
# We allow omitted arguments in action invocations.
#
$ list =~ s/^,/-,/ ;
$ list =~ s/,$/,-/ ;
$ list =~ s/,,/,-,/g ;
2012-12-09 19:45:29 +01:00
my @ list1 = split /,/ , $ list ;
my @ list2 ;
my $ element = '' ;
my $ opencount = 0 ;
for ( @ list1 ) {
my $ count ;
if ( ( $ count = tr /(/ ( / ) > 0 ) {
$ opencount += $ count ;
if ( $ element eq '' ) {
$ element = $ _ ;
} else {
$ element = join ( ',' , $ element , $ _ ) ;
}
if ( ( $ count = tr /)/ ) / ) > 0 ) {
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
fatal_error "Invalid $type ($list)" if $ opencount < 0 ;
}
}
} elsif ( ( $ count = tr /)/ ) / ) > 0 ) {
fatal_error "Invalid $type ($list)" if $ element eq '' ;
$ element = join ( ',' , $ element , $ _ ) ;
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
fatal_error "Invalid $type ($list)" if $ opencount < 0 ;
}
} elsif ( $ element eq '' ) {
push @ list2 , $ _ ;
} else {
$ element = join ',' , $ element , $ _ ;
}
}
unless ( $ opencount == 0 ) {
fatal_error "Invalid $type ($list)" ;
}
@ list2 ;
}
2014-12-24 00:25:20 +01:00
#
# Splits the columns of a config file record
#
2013-12-01 18:24:49 +01:00
sub split_columns ( $ ) {
2013-11-30 23:13:42 +01:00
my ( $ list ) = @ _ ;
return split ' ' , $ list unless $ list =~ /\(/ ;
my @ list1 = split ' ' , $ list ;
my @ list2 ;
my $ element = '' ;
my $ opencount = 0 ;
for ( @ list1 ) {
my $ count ;
if ( ( $ count = tr /(/ ( / ) > 0 ) {
$ opencount += $ count ;
if ( $ element eq '' ) {
$ element = $ _ ;
} else {
2013-12-29 17:56:14 +01:00
$ element = join ( ' ' , $ element , $ _ ) ;
2013-11-30 23:13:42 +01:00
}
if ( ( $ count = tr /)/ ) / ) > 0 ) {
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
2013-12-01 18:24:49 +01:00
fatal_error "Mismatched parentheses ($_)" if $ opencount < 0 ;
2013-11-30 23:13:42 +01:00
}
}
} elsif ( ( $ count = tr /)/ ) / ) > 0 ) {
2013-12-29 17:56:14 +01:00
$ element = join ( ' ' , $ element , $ _ ) ;
2013-11-30 23:13:42 +01:00
if ( ! ( $ opencount -= $ count ) ) {
push @ list2 , $ element ;
$ element = '' ;
} else {
2013-12-01 18:24:49 +01:00
fatal_error "Mismatched parentheses ($_)" if $ opencount < 0 ;
2013-11-30 23:13:42 +01:00
}
} elsif ( $ element eq '' ) {
push @ list2 , $ _ ;
} else {
2013-12-29 17:56:14 +01:00
$ element = join ' ' , $ element , $ _ ;
2013-11-30 23:13:42 +01:00
}
}
unless ( $ opencount == 0 ) {
fatal_error "Mismatched parentheses ($list)" ;
}
@ list2 ;
}
2011-06-12 00:40:55 +02:00
#
# Determine if a value has been supplied
#
sub supplied ( $ ) {
my $ val = shift ;
defined $ val && $ val ne '' ;
}
2009-02-22 18:30:14 +01:00
#
# Pre-process a line from a configuration file.
# ensure that it has an appropriate number of columns.
# supply '-' in omitted trailing columns.
2011-10-02 20:45:55 +02:00
# Handles all of the supported forms of column/pair specification
2013-08-06 16:05:47 +02:00
# Handles segragating raw iptables input in INLINE rules
2009-02-22 18:30:14 +01:00
#
2013-12-14 22:35:01 +01:00
sub split_line2 ( $$;$$$ ) {
my ( $ description , $ columnsref , $ nopad , $ maxcolumns , $ inline ) = @ _ ;
2011-10-01 20:39:12 +02:00
2013-12-15 20:23:20 +01:00
my $ inlinematches = $ config { INLINE_MATCHES } ;
2015-09-02 19:24:31 +02:00
my ( $ columns , $ pairs , $ rest ) ;
my $ currline = $ currentline ;
2012-05-07 20:59:47 +02:00
unless ( defined $ maxcolumns ) {
my @ maxcolumns = ( keys %$ columnsref ) ;
$ maxcolumns = @ maxcolumns ;
}
2013-04-11 21:57:59 +02:00
$ inline_matches = '' ;
2011-10-02 20:45:55 +02:00
#
2015-09-02 19:24:31 +02:00
# First, see if there are double semicolons on the line; what follows will be raw iptables input
#
if ( $ inline ) {
( $ columns , $ pairs , $ rest ) = split ';;' , $ currline ;
if ( defined $ pairs ) {
2015-09-02 22:07:33 +02:00
fatal_error "Only one set of double semicolons (';;') allowed on a line" if defined $ rest ;
2015-09-02 19:24:31 +02:00
$ currline = $ columns ;
$ inline_matches = $ pairs ;
#
# Don't look for matches below
#
$ inline = $ inlinematches = '' ;
}
}
#
# Next, see if there is a semicolon on the line; what follows will be column/value pairs or raw iptables input
2011-10-02 20:45:55 +02:00
#
2015-09-02 19:24:31 +02:00
( $ columns , $ pairs , $ rest ) = split ( ';' , $ currline ) ;
2009-02-22 18:30:14 +01:00
2011-10-02 20:45:55 +02:00
if ( supplied $ pairs ) {
#
# Found it -- be sure there wasn't more than one.
#
fatal_error "Only one semicolon (';') allowed on a line" if defined $ rest ;
2013-04-11 21:57:59 +02:00
2013-12-15 20:23:20 +01:00
if ( $ inlinematches ) {
fatal_error "The $description does not support inline matches (INLINE_MATCHES=Yes)" unless $ inline ;
$ inline_matches = $ pairs ;
if ( $ columns =~ /^(\s*|.*[^&@%]){(.*)}\s*$/ ) {
#
# Pairs are enclosed in curly brackets.
#
$ columns = $ 1 ;
$ pairs = $ 2 ;
} else {
$ pairs = '' ;
}
} elsif ( $ inline ) {
2013-12-14 22:35:01 +01:00
#
2013-12-29 19:13:00 +01:00
# This file supports INLINE or IPTABLES
2013-12-14 22:35:01 +01:00
#
2015-09-02 19:24:31 +02:00
if ( $ currline =~ /^\s*INLINE(?:\(.*\)(:.*)?|:.*)?\s/ || $ currline =~ /^\s*IP6?TABLES(?:\(.*\)|:.*)?\s/ ) {
2013-12-14 22:35:01 +01:00
$ inline_matches = $ pairs ;
2013-04-11 21:57:59 +02:00
2013-12-14 22:35:01 +01:00
if ( $ columns =~ /^(\s*|.*[^&@%]){(.*)}\s*$/ ) {
#
# Pairs are enclosed in curly brackets.
#
$ columns = $ 1 ;
$ pairs = $ 2 ;
} else {
2013-12-15 20:23:20 +01:00
warning_message "This entry needs to be changed before INLINE_MATCHES can be set to Yes" if $ checkinline ;
2013-12-14 22:35:01 +01:00
$ pairs = '' ;
}
}
2013-12-15 20:23:20 +01:00
} elsif ( $ checkinline ) {
warning_message "This entry needs to be changed before INLINE_MATCHES can be set to Yes" ;
2013-04-11 21:57:59 +02:00
}
2015-09-02 19:24:31 +02:00
} elsif ( $ currline =~ /^(\s*|.*[^&@%]){(.*)}$/ ) {
2011-10-02 20:45:55 +02:00
#
# Pairs are enclosed in curly brackets.
#
$ columns = $ 1 ;
$ pairs = $ 2 ;
} else {
$ pairs = '' ;
}
2011-09-26 02:08:53 +02:00
fatal_error "Shorewall Configuration file entries may not contain double quotes, single back quotes or backslashes" if $ columns =~ /["`\\]/ ;
fatal_error "Non-ASCII gunk in file" if $ columns =~ /[^\s[:print:]]/ ;
2009-02-22 18:30:14 +01:00
2013-12-01 18:24:49 +01:00
my @ line = split_columns ( $ columns ) ;
2009-02-22 18:30:14 +01:00
2012-12-24 18:31:20 +01:00
$ nopad = { } unless $ nopad ;
2009-02-22 18:30:14 +01:00
2011-10-02 20:45:55 +02:00
my $ first = supplied $ line [ 0 ] ? $ line [ 0 ] : '-' ;
2011-09-26 02:08:53 +02:00
my $ npcolumns = $ nopad - > { $ first } ;
2009-02-22 18:30:14 +01:00
2011-09-26 02:08:53 +02:00
if ( defined $ npcolumns ) {
fatal_error "Invalid $first entry" if $ npcolumns && @ line != $ npcolumns ;
2009-02-22 18:30:14 +01:00
return @ line
}
2015-09-02 19:24:31 +02:00
fatal_error "Shorewall Configuration file entries may not contain single quotes" if $ currline =~ /'/ ;
2009-02-22 18:30:14 +01:00
my $ line = @ line ;
fatal_error "Invalid $description entry (too many columns)" if $ line > $ maxcolumns ;
$ line - - while $ line > 0 && $ line [ $ line - 1 ] eq '-' ;
push @ line , '-' while @ line < $ maxcolumns ;
2011-09-26 02:08:53 +02:00
if ( supplied $ pairs ) {
2011-10-02 20:45:55 +02:00
$ pairs =~ s/^\s*// ;
$ pairs =~ s/\s*$// ;
2013-04-11 21:57:59 +02:00
my @ pairs = split ( /,?\s+/ , $ pairs ) ;
for ( @ pairs ) {
fatal_error "Invalid column/value pair ($_)" unless /^(\w+)(?:=>?|:)(.+)$/ ;
my ( $ column , $ value ) = ( lc $ 1 , $ 2 ) ;
fatal_error "Unknown column ($1)" unless exists $ columnsref - > { $ column } ;
$ column = $ columnsref - > { $ column } ;
fatal_error "Non-ASCII gunk in file" if $ columns =~ /[^\s[:print:]]/ ;
$ value = $ 1 if $ value =~ /^"([^"]+)"$/ ;
fatal_error "Column values may not contain embedded double quotes, single back quotes or backslashes" if $ columns =~ /["`\\]/ ;
fatal_error "Non-ASCII gunk in the value of the $column column" if $ columns =~ /[^\s[:print:]]/ ;
$ line [ $ column ] = $ value ;
2011-09-26 02:08:53 +02:00
}
2012-04-24 23:52:57 +02:00
}
2011-09-26 02:08:53 +02:00
2009-02-22 18:30:14 +01:00
@ line ;
}
2013-12-14 22:35:01 +01:00
sub split_line1 ( $$;$$ ) {
& split_line2 ( @ _ , undef ) ;
}
2011-10-02 20:45:55 +02:00
sub split_line ($$) {
& split_line1 ( @ _ , { } ) ;
}
2013-02-19 00:15:26 +01:00
sub have_capability ( $ ; $ ) ;
2012-12-22 22:51:24 +01:00
#
# Returns True if there is a current COMMENT or if COMMENTS are not available.
#
sub no_comment () {
$ comment ? 1 : ! have_capability ( 'COMMENTS' ) ;
}
#
# Clear the $comment variable and the comment stack
#
sub clear_comment () {
2012-12-24 21:35:08 +01:00
$ comment = '' ;
2012-12-26 02:00:24 +01:00
$ nocomment = 0 ;
2012-12-22 22:51:24 +01:00
}
2013-09-23 21:21:44 +02:00
#
# Set the current comment
#
sub set_comment ( $ ) {
( $ comment ) = @ _ ;
}
2012-12-22 22:51:24 +01:00
#
# Push and Pop comment stack
#
2012-12-26 02:00:24 +01:00
sub push_comment () {
my $ return = $ comment ;
$ comment = '' ;
$ return ;
2012-12-22 22:51:24 +01:00
}
2012-12-26 02:00:24 +01:00
sub pop_comment ( $ ) {
$ comment = $ _ [ 0 ] ;
2012-12-22 22:51:24 +01:00
}
#
# Set $comment to the passed unless there is a current comment
#
sub macro_comment ( $ ) {
my $ macro = $ _ [ 0 ] ;
$ comment = $ macro unless $ comment || ! ( have_capability ( 'COMMENTS' ) && $ config { AUTOCOMMENT } ) ;
}
2013-11-18 15:57:54 +01:00
#
# Set/clear $section_function
#
sub set_section_function ( \& ) {
$ section_function = $ _ [ 0 ] ;
}
sub clear_section_function () {
$ section_function = undef ;
}
2009-02-22 18:30:14 +01:00
#
# Open a file, setting $currentfile. Returns the file's absolute pathname if the file
# exists, is non-empty and was successfully opened. Terminates with a fatal error
# if the file exists, is non-empty, but the open fails.
#
sub do_open_file ( $ ) {
my $ fname = $ _ [ 0 ] ;
open $ currentfile , '<' , $ fname or fatal_error "Unable to open $fname: $!" ;
$ currentlinenumber = 0 ;
2012-03-19 15:38:52 +01:00
$ ifstack = @ ifstack ;
2009-02-22 18:30:14 +01:00
$ currentfilename = $ fname ;
}
2012-12-25 17:10:48 +01:00
#
# Arguments are:
#
# - file name
# - Maximum value allowed in ?FORMAT directives
# - ?COMMENT allowed in this file
# - Ignore ?COMMENT in ths file
#
2015-08-15 01:11:41 +02:00
sub open_file ( $;$$$$ ) {
my ( $ fname , $ mf , $ ca , $ nc , $ cf ) = @ _ ;
2012-12-24 21:35:08 +01:00
$ fname = find_file $ fname ;
2009-02-22 18:30:14 +01:00
2009-03-09 21:56:53 +01:00
assert ( ! defined $ currentfile ) ;
2009-02-22 18:30:14 +01:00
2010-09-28 01:16:29 +02:00
if ( - f $ fname && - s _ ) {
2012-12-23 19:49:32 +01:00
$ first_entry = 0 ;
2015-08-15 01:11:41 +02:00
$ file_format = supplied $ cf ? $ cf : 1 ;
2012-12-24 21:35:08 +01:00
$ max_format = supplied $ mf ? $ mf : 1 ;
$ comments_allowed = supplied $ ca ? $ ca : 0 ;
2012-12-24 22:35:42 +01:00
$ nocomment = $ nc ;
2010-09-28 01:16:29 +02:00
do_open_file $ fname ; ;
} else {
2012-03-19 15:38:52 +01:00
$ ifstack = @ ifstack ;
2010-09-28 01:16:29 +02:00
'' ;
}
2009-02-22 18:30:14 +01:00
}
2012-12-24 22:35:42 +01:00
#
# Push open-specific globals onto the include stack
#
sub push_include () {
push @ includestack , [ $ currentfile ,
$ currentfilename ,
$ currentlinenumber ,
$ ifstack ,
$ file_format ,
$ max_format ,
$ comment ,
2013-11-18 15:57:54 +01:00
$ nocomment ,
$ section_function ] ;
2012-12-24 22:35:42 +01:00
}
2009-02-22 18:30:14 +01:00
#
# Pop the include stack
#
sub pop_include () {
my $ arrayref = pop @ includestack ;
2012-03-16 16:16:12 +01:00
unless ( $ ifstack == @ ifstack ) {
my $ lastref = $ ifstack [ - 1 ] ;
$ currentlinenumber = 'EOF' ;
2012-03-19 03:10:46 +01:00
fatal_error qq( Missing "?ENDIF" to match ?IF at line number $lastref->[2] )
2012-03-16 16:16:12 +01:00
}
2009-02-22 18:30:14 +01:00
if ( $ arrayref ) {
2012-12-24 22:35:42 +01:00
( $ currentfile ,
$ currentfilename ,
$ currentlinenumber ,
$ ifstack ,
$ file_format ,
$ max_format ,
$ comment ,
2013-11-18 15:57:54 +01:00
$ nocomment ,
$ section_function ) = @$ arrayref ;
2009-02-22 18:30:14 +01:00
} else {
2012-03-16 16:16:12 +01:00
$ currentfile = undef ;
$ currentlinenumber = 'EOF' ;
2012-12-24 21:35:08 +01:00
clear_comment ;
2013-11-18 15:57:54 +01:00
clear_section_function ;
2009-02-22 18:30:14 +01:00
}
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
#
# This function is normally called below in read_a_line() when EOF is reached. Clients of the
# module may also call the function to close the file before EOF
#
sub close_file () {
if ( $ currentfile ) {
my $ result = close $ currentfile ;
pop_include ;
fatal_error "SHELL Script failed" unless $ result ;
2012-12-23 19:49:32 +01:00
$ first_entry = 0 ;
2009-02-22 18:30:14 +01:00
}
}
2013-06-01 22:03:10 +02:00
#
# Clear the current filename
#
sub clear_currentfilename () {
$ currentfilename = '' ;
}
2012-04-06 20:49:59 +02:00
#
2012-06-29 18:01:26 +02:00
# Process an ?IF, ?ELSIF, ?ELSE or ?END directive
2012-04-06 20:49:59 +02:00
#
2012-04-07 16:16:17 +02:00
2012-06-03 22:47:38 +02:00
#
2012-12-05 23:53:03 +01:00
# Report an error or warning from process_compiler_directive()
2012-06-03 22:47:38 +02:00
#
2012-12-05 23:53:03 +01:00
sub directive_error ( $$$ ) {
2012-06-29 18:01:26 +02:00
$ currentfilename = $ _ [ 1 ] ;
$ currentlinenumber = $ _ [ 2 ] ;
fatal_error $ _ [ 0 ] ;
2012-06-03 22:47:38 +02:00
}
2012-12-05 23:53:03 +01:00
sub directive_warning ( $$$ ) {
2012-12-04 23:28:03 +01:00
my ( $ savefilename , $ savelineno ) = ( $ currentfilename , $ currentlinenumber ) ;
( my $ warning , $ currentfilename , $ currentlinenumber ) = @ _ ;
warning_message $ warning ;
( $ currentfilename , $ currentlinenumber ) = ( $ savefilename , $ savelineno ) ;
}
2012-12-13 15:46:57 +01:00
#
# Add quotes to the passed value if the passed 'first part' has an odd number of quotes
# Return an expression that concatenates $first, $val and $rest
#
2012-12-16 01:12:03 +01:00
sub join_parts ( $$$ ) {
2012-12-13 15:46:57 +01:00
my ( $ first , $ val , $ rest ) = @ _ ;
$ val = '' unless defined $ val ;
$ val = "'$val'" unless ( $ val =~ /^-?\d+$/ || # Value is numeric
( ( ( $ first =~ tr /"/ " / ) & 1 ) || # There are an odd number of double quotes preceding the value
( ( $ first =~ tr /'/ ' / ) & 1 ) ) ) ; # There are an odd number of single quotes preceding the value
join ( '' , $ first , $ val , $ rest ) ;
}
2012-06-28 00:15:44 +02:00
#
2012-12-05 23:53:03 +01:00
# Evaluate an expression in an ?IF, ?ELSIF or ?SET directive
2012-06-28 00:15:44 +02:00
#
2012-06-29 18:01:26 +02:00
sub evaluate_expression ( $$$ ) {
2012-07-06 15:43:15 +02:00
my ( $ expression , $ filename , $ linenumber ) = @ _ ;
2012-07-07 18:47:10 +02:00
my $ val ;
2012-06-28 00:15:44 +02:00
my $ count = 0 ;
2012-12-12 22:13:17 +01:00
my $ chain = $ actparms { chain } ;
2012-12-04 17:49:59 +01:00
# $1 $2 $3 - $4
while ( $ expression =~ m ( ^(.*?) \ $( { ) ? ( \ d + | [ a - zA - Z_ ] \ w * ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
2012-06-28 00:15:44 +02:00
my ( $ first , $ var , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
2012-03-19 03:10:46 +01:00
2012-12-12 20:46:38 +01:00
if ( $ var =~ /^\d+$/ ) {
2012-12-12 22:13:17 +01:00
fatal_error "Action parameters (\$$var) may only be referenced within the body of an action" unless $ chain ;
2012-12-12 20:46:38 +01:00
$ val = $ var ? $ actparms { $ var } : $ actparms { 0 } - > { name } ;
} else {
$ val = ( exists $ variables { $ var } ? $ variables { $ var } :
exists $ capdesc { $ var } ? have_capability ( $ var ) : '' ) ;
}
2012-12-05 16:51:41 +01:00
2012-12-16 01:12:03 +01:00
$ expression = join_parts ( $ first , $ val , $ rest ) ;
2012-12-05 23:53:03 +01:00
directive_error ( "Variable Expansion Loop" , $ filename , $ linenumber ) if + + $ count > 100 ;
2012-04-10 00:12:13 +02:00
}
2012-03-19 03:10:46 +01:00
2012-12-12 22:13:17 +01:00
if ( $ chain ) {
2012-12-12 20:46:38 +01:00
# $1 $2 $3 - $4
2012-12-13 15:46:57 +01:00
while ( $ expression =~ m ( ^(.*?) \ @ ( { ) ? ( \ d + | [ a - zA - Z ] \ w * ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
2012-12-12 20:46:38 +01:00
my ( $ first , $ var , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
2013-01-20 23:51:16 +01:00
$ var = numeric_value ( $ var ) if $ var =~ /^\d/ ;
2012-12-12 22:13:17 +01:00
$ val = $ var ? $ actparms { $ var } : $ chain ;
2013-01-20 23:51:16 +01:00
$ parmsmodified || = $ var eq 'caller' ;
2012-12-16 01:12:03 +01:00
$ expression = join_parts ( $ first , $ val , $ rest ) ;
2012-12-12 20:46:38 +01:00
directive_error ( "Variable Expansion Loop" , $ filename , $ linenumber ) if + + $ count > 100 ;
}
}
2012-06-28 00:15:44 +02:00
# $1 $2 $3 - $4
while ( $ expression =~ m ( ^(.*?) __ ( { ) ? ( \ w + ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
my ( $ first , $ cap , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
2012-07-07 18:47:10 +02:00
2012-06-28 00:15:44 +02:00
if ( exists $ capdesc { $ cap } ) {
2012-08-07 00:54:45 +02:00
$ val = have_capability ( $ cap ) ;
if ( defined $ val ) {
$ val = "'$val'" unless $ val =~ /^-?\d+$/ ;
} else {
$ val = 0 ;
}
2012-07-06 15:43:15 +02:00
} elsif ( $ cap =~ /^IPV([46])$/ ) {
2012-12-05 17:37:50 +01:00
$ val = ( $ family == $ 1 ) || 0 ;
2012-06-28 00:15:44 +02:00
} else {
2012-12-05 23:53:03 +01:00
directive_error "Unknown capability ($cap)" , $ filename , $ linenumber ;
2012-06-28 00:15:44 +02:00
}
2012-03-19 15:38:52 +01:00
2012-12-05 03:10:19 +01:00
$ expression = join ( '' , $ first , $ val , $ rest ) ;
2012-06-28 00:15:44 +02:00
}
2012-07-08 16:48:27 +02:00
$ expression =~ s/^\s*(.+)\s*$/$1/ ;
2012-12-05 17:37:50 +01:00
print "EXPR=> $expression\n" if $ debug ;
2013-02-11 00:19:30 +01:00
if ( $ expression =~ /^\d+$/ ) {
$ val = $ expression
} else {
2012-07-06 16:26:54 +02:00
#
2012-07-08 16:48:27 +02:00
# Not a simple one-term expression -- compile it
2012-07-06 16:26:54 +02:00
#
$ val = eval qq( package Shorewall::User;\nuse strict;\n# line $linenumber "$filename"\n$expression ) ;
unless ( $ val ) {
2012-12-05 23:53:03 +01:00
directive_error ( "Couldn't parse expression ($expression): $@" , $ filename , $ linenumber ) if $@ ;
2012-12-05 17:37:50 +01:00
$ val = '' unless defined $ val ;
2012-07-06 16:26:54 +02:00
}
2012-06-28 00:15:44 +02:00
}
2012-03-19 03:10:46 +01:00
2012-06-28 00:15:44 +02:00
$ val ;
}
2012-03-19 03:10:46 +01:00
2014-02-17 21:50:59 +01:00
#
# Set callback
#
sub directive_callback ( $ ) {
$ directive_callback = shift ;
}
2012-06-28 00:15:44 +02:00
#
# Each entry in @ifstack consists of a 4-tupple
#
# [0] = The keyword (IF,ELSIF or ELSE)
# [1] = True if we were already omitting at the last IF directive
# [2] = True if we have included any block of the current IF...ELSEIF....ELSEIF... sequence.
# [3] = The line number of the directive
#
2012-12-05 23:53:03 +01:00
sub process_compiler_directive ( $$$$ ) {
2012-06-29 18:01:26 +02:00
my ( $ omitting , $ line , $ filename , $ linenumber ) = @ _ ;
2012-03-19 19:57:33 +01:00
2012-06-28 00:15:44 +02:00
print "CD===> $line\n" if $ debug ;
2012-03-19 19:57:33 +01:00
2012-12-23 19:49:32 +01:00
directive_error ( "Invalid compiler directive ($line)" , $ filename , $ linenumber ) unless $ line =~ /^\s*\?(IF\s+|ELSE|ELSIF\s+|ENDIF|SET\s+|RESET\s+|FORMAT\s+|COMMENT\s*)(.*)$/i ;
2012-03-19 03:10:46 +01:00
2012-08-09 19:30:02 +02:00
my ( $ keyword , $ expression ) = ( uc $ 1 , $ 2 ) ;
2012-03-19 15:38:52 +01:00
2012-12-22 17:14:46 +01:00
$ keyword =~ s/\s*$// ;
2012-06-28 00:15:44 +02:00
if ( supplied $ expression ) {
$ expression =~ s/#.*// ;
$ expression =~ s/\s*$// ;
} else {
$ expression = '' ;
}
my ( $ lastkeyword , $ prioromit , $ included , $ lastlinenumber ) = @ ifstack ? @ { $ ifstack [ - 1 ] } : ( '' , 0 , 0 , 0 ) ;
2014-02-17 21:50:59 +01:00
my % directives =
( IF = > sub ( ) {
directive_error ( "Missing IF expression" , $ filename , $ linenumber ) unless supplied $ expression ;
my $ nextomitting = $ omitting || ! evaluate_expression ( $ expression , $ filename , $ linenumber ) ;
push @ ifstack , [ 'IF' , $ omitting , ! $ nextomitting , $ linenumber ] ;
$ omitting = $ nextomitting ;
} ,
ELSIF = > sub ( ) {
directive_error ( "?ELSIF has no matching ?IF" , $ filename , $ linenumber ) unless @ ifstack > $ ifstack && $ lastkeyword =~ /IF/ ;
directive_error ( "Missing IF expression" , $ filename , $ linenumber ) unless $ expression ;
if ( $ omitting && ! $ included ) {
#
# We can only change to including if we were previously omitting
#
$ omitting = $ prioromit || ! evaluate_expression ( $ expression , $ filename , $ linenumber ) ;
$ included = ! $ omitting ;
} else {
#
# We have already included -- so we don't want to include this part
#
$ omitting = 1 ;
}
$ ifstack [ - 1 ] = [ 'ELSIF' , $ prioromit , $ included , $ lastlinenumber ] ;
} ,
ELSE = > sub ( ) {
directive_error ( "Invalid ?ELSE" , $ filename , $ linenumber ) unless $ expression eq '' ;
directive_error ( "?ELSE has no matching ?IF" , $ filename , $ linenumber ) unless @ ifstack > $ ifstack && $ lastkeyword =~ /IF/ ;
$ omitting = $ included || ! $ omitting unless $ prioromit ;
$ ifstack [ - 1 ] = [ 'ELSE' , $ prioromit , 1 , $ lastlinenumber ] ;
} ,
ENDIF = > sub ( ) {
directive_error ( "Invalid ?ENDIF" , $ filename , $ linenumber ) unless $ expression eq '' ;
directive_error ( q( Unexpected "?ENDIF" without matching ?IF or ?ELSE ) , $ filename , $ linenumber ) if @ ifstack <= $ ifstack ;
$ omitting = $ prioromit ;
pop @ ifstack ;
} ,
SET = > sub ( ) {
unless ( $ omitting ) {
directive_error ( "Missing SET variable" , $ filename , $ linenumber ) unless supplied $ expression ;
( my $ var , $ expression ) = split ' ' , $ expression , 2 ;
directive_error ( "Invalid SET variable ($var)" , $ filename , $ linenumber ) unless $ var =~ /^(\$)?([a-zA-Z]\w*)$/ || $ var =~ /^(@)(\d+|[a-zA-Z]\w*)/ ;
directive_error ( "Missing SET expression" , $ filename , $ linenumber ) unless supplied $ expression ;
if ( ( $ 1 || '' ) eq '@' ) {
$ var = $ 2 ;
$ var = numeric_value ( $ var ) if $ var =~ /^\d/ ;
$ var = $ 2 || 'chain' ;
directive_error ( "Shorewall variables may only be SET in the body of an action" , $ filename , $ linenumber ) unless $ actparms { 0 } ;
my $ val = $ actparms { $ var } = evaluate_expression ( $ expression ,
$ filename ,
$ linenumber ) ;
$ parmsmodified = 1 ;
} else {
$ variables { $ 2 } = evaluate_expression ( $ expression ,
$ filename ,
$ linenumber ) ;
}
}
} ,
'FORMAT' = > sub ( ) {
unless ( $ omitting ) {
directive_error ( "?FORMAT is not allowed in this file" , $ filename , $ linenumber ) unless $ max_format > 1 ;
directive_error ( "Missing format" , $ filename , $ linenumber ) unless supplied $ expression ;
directive_error ( "Invalid format ($expression)" , $ filename , $ linenumber ) unless $ expression =~ /^\d+$/ ;
directive_error ( "Format must be between 1 and $max_format" , $ filename , $ linenumber ) unless $ expression && $ expression <= $ max_format ;
$ file_format = $ expression ;
}
} ,
RESET = > sub ( ) {
unless ( $ omitting ) {
my $ var = $ expression ;
directive_error ( "Missing RESET variable" , $ filename , $ linenumber ) unless supplied $ var ;
directive_error ( "Invalid RESET variable ($var)" , $ filename , $ linenumber ) unless $ var =~ /^(\$)?([a-zA-Z]\w*)$/ || $ var =~ /^(@)(\d+|[a-zA-Z]\w*)/ ;
if ( ( $ 1 || '' ) eq '@' ) {
$ var = numeric_value ( $ var ) if $ var =~ /^\d/ ;
$ var = $ 2 || 'chain' ;
directive_error ( "Shorewall variables may only be RESET in the body of an action" , $ filename , $ linenumber ) unless $ actparms { 0 } ;
if ( exists $ actparms { $ var } ) {
if ( $ var =~ /^loglevel|logtag|chain|disposition|caller$/ ) {
$ actparms { $ var } = '' ;
} else {
delete $ actparms { $ var }
}
} else {
directive_warning ( "Shorewall variable $2 does not exist" , $ filename , $ linenumber ) ;
}
} else {
if ( exists $ variables { $ 2 } ) {
delete $ variables { $ 2 } ;
} else {
directive_warning ( "Shell variable $2 does not exist" , $ filename , $ linenumber ) ;
}
}
}
} ,
COMMENT = > sub ( ) {
unless ( $ omitting ) {
if ( $ comments_allowed ) {
unless ( $ nocomment ) {
if ( have_capability ( 'COMMENTS' ) ) {
( $ comment = $ line ) =~ s/^\s*\?COMMENT\s*// ;
$ comment =~ s/\s*$// ;
} else {
directive_warning ( "COMMENTs ignored -- require comment support in iptables/Netfilter" , $ filename , $ linenumber ) unless $ warningcount + + ;
}
}
} else {
directive_error ( "?COMMENT is not allowed in this file" , $ filename , $ linenumber ) ;
}
}
}
) ;
2012-12-22 17:14:46 +01:00
if ( my $ function = $ directives { $ keyword } ) {
$ function - > ( ) ;
} else {
assert ( 0 , $ keyword ) ;
2012-03-19 03:10:46 +01:00
}
2014-02-17 21:50:59 +01:00
if ( $ directive_callback ) {
$ directive_callback - > ( $ keyword , $ line )
} else {
$ omitting ;
}
2012-04-24 23:52:57 +02:00
}
2012-03-19 03:10:46 +01:00
2011-01-16 00:43:45 +01:00
#
2011-07-02 17:10:43 +02:00
# Functions for copying a file into the script
2011-01-16 00:43:45 +01:00
#
2011-08-08 23:37:47 +02:00
sub copy ( $ ) {
2011-01-16 00:43:45 +01:00
assert ( $ script_enabled ) ;
if ( $ script ) {
2012-03-19 21:38:24 +01:00
my $ file = $ _ [ 0 ] ;
my $ omitting = 0 ;
my $ save_ifstack = $ ifstack ;
my $ lineno = 0 ;
$ ifstack = @ ifstack ;
2011-01-16 00:43:45 +01:00
open IF , $ file or fatal_error "Unable to open $file: $!" ;
while ( <IF> ) {
chomp ;
2012-03-19 21:38:24 +01:00
$ lineno + + ;
if ( /^\s*\?/ ) {
2012-12-05 23:53:03 +01:00
$ omitting = process_compiler_directive ( $ omitting , $ _ , $ file , $ lineno ) ;
2012-03-19 21:38:24 +01:00
next ;
}
next if $ omitting ;
2011-01-16 00:43:45 +01:00
if ( /^\s*$/ ) {
print $ script "\n" unless $ lastlineblank ;
$ lastlineblank = 1 ;
} else {
if ( $ indent ) {
s/^(\s*)/$indent1$1$indent2/ ;
s/ /\t/ if $ indent2 ;
}
print $ script $ _ ;
print $ script "\n" ;
$ lastlineblank = 0 ;
}
}
2012-03-19 21:38:24 +01:00
if ( $ ifstack < @ ifstack ) {
$ currentlinenumber = 'EOF' ;
$ currentfilename = $ file ;
fatal_error "Missing ?ENDIF to match the ?IF at line $ifstack[-1]->[3]" ;
} else {
$ ifstack = $ save_ifstack ;
}
2011-01-16 00:43:45 +01:00
close IF ;
}
}
#
# This variant of copy handles line continuation, 'here documents' and INCLUDE
#
sub copy1 ( $ ) {
assert ( $ script_enabled ) ;
my $ result = 0 ;
if ( $ script || $ debug ) {
my ( $ do_indent , $ here_documents ) = ( 1 , '' ) ;
open_file ( $ _ [ 0 ] ) ;
2012-04-24 23:52:57 +02:00
2011-01-16 00:43:45 +01:00
while ( $ currentfile ) {
while ( <$currentfile> ) {
$ currentlinenumber + + ;
chomp ;
2012-03-19 21:38:24 +01:00
if ( /^\s*\?/ ) {
2012-12-05 23:53:03 +01:00
$ omitting = process_compiler_directive ( $ omitting , $ _ , $ currentfilename , $ currentlinenumber ) ;
2012-03-19 21:38:24 +01:00
next ;
}
2011-01-16 00:43:45 +01:00
if ( /^${here_documents}\s*$/ ) {
if ( $ script ) {
print $ script $ here_documents if $ here_documents ;
print $ script "\n" ;
}
if ( $ debug ) {
print "GS-----> $here_documents" if $ here_documents ;
print "GS----->\n" ;
}
$ do_indent = 1 ;
$ here_documents = '' ;
next ;
}
if ( $ do_indent && /.*<<\s*([^ ]+)s*(.*)/ ) {
$ here_documents = $ 1 ;
s/^(\s*)/$indent1$1$indent2/ ;
s/ /\t/ if $ indent2 ;
$ do_indent = 0 ;
if ( $ script ) {
print $ script $ _ ;
print $ script "\n" ;
}
if ( $ debug ) {
s/\n/\nGS-----> /g ;
print "GS-----> $_\n" ;
}
$ result = 1 ;
next ;
}
if ( $ do_indent ) {
2011-01-18 23:58:56 +01:00
if ( /^\s*INCLUDE\b/ ) {
2011-01-16 00:43:45 +01:00
my @ line = split / / ;
fatal_error "Invalid INCLUDE command" if @ line != 2 ;
fatal_error "INCLUDEs nested too deeply" if @ includestack >= 4 ;
my $ filename = find_file $ line [ 1 ] ;
2011-11-06 23:46:14 +01:00
warning_message "Reserved filename ($1) in INCLUDE directive" if $ filename =~ '/(.*)' && $ config_files { $ 1 } ;
2011-01-16 00:43:45 +01:00
fatal_error "INCLUDE file $filename not found" unless - f $ filename ;
fatal_error "Directory ($filename) not allowed in INCLUDE" if - d _ ;
if ( - s _ ) {
2012-12-24 22:35:42 +01:00
push_include ;
2011-01-16 00:43:45 +01:00
$ currentfile = undef ;
do_open_file $ filename ;
} else {
$ currentlinenumber = 0 ;
}
next ;
}
2012-04-24 23:52:57 +02:00
2011-01-16 00:43:45 +01:00
if ( $ indent ) {
s/^(\s*)/$indent1$1$indent2/ ;
s/ /\t/ if $ indent2 ;
}
}
if ( $ script ) {
print $ script $ _ ;
print $ script "\n" ;
}
$ do_indent = ! ( $ here_documents || /\\$/ ) ;
$ result = 1 unless $ result || /^\s*$/ || /^\s*#/ ;
if ( $ debug ) {
s/\n/\nGS-----> /g ;
print "GS-----> $_\n" ;
}
}
close_file ;
}
}
$ lastlineblank = 0 ;
$ result ;
}
#
# This one drops header comments and replaces them with a three-line banner
#
sub copy2 ( $$ ) {
my ( $ file , $ trace ) = @ _ ;
assert ( $ script_enabled ) ;
my $ empty = 1 ;
if ( $ script || $ trace ) {
my $ file = $ _ [ 0 ] ;
2012-03-19 21:38:24 +01:00
my $ omitting = 0 ;
my $ save_ifstack = $ ifstack ;
my $ lineno = 0 ;
2011-01-16 00:43:45 +01:00
open IF , $ file or fatal_error "Unable to open $file: $!" ;
while ( <IF> ) {
2012-03-19 21:38:24 +01:00
$ lineno + + ;
2011-01-16 00:43:45 +01:00
$ empty = 0 , last unless /^#/ ;
}
unless ( $ empty ) {
emit << EOF ;
################################################################################
# Functions imported from $file
################################################################################
EOF
chomp ;
emit ( $ _ ) unless /^\s*$/ ;
while ( <IF> ) {
2012-03-19 21:38:24 +01:00
$ lineno + + ;
2011-01-16 00:43:45 +01:00
chomp ;
2012-03-19 21:38:24 +01:00
if ( /^\s*\?/ ) {
2012-12-05 23:53:03 +01:00
$ omitting = process_compiler_directive ( $ omitting , $ _ , $ file , $ lineno ) ;
2012-03-19 21:38:24 +01:00
next ;
}
next if $ omitting ;
2011-01-16 00:43:45 +01:00
if ( /^\s*$/ ) {
unless ( $ lastlineblank ) {
print $ script "\n" if $ script ;
print "GS----->\n" if $ trace ;
}
$ lastlineblank = 1 ;
} else {
if ( $ indent ) {
s/^(\s*)/$indent1$1$indent2/ ;
s/ /\t/ if $ indent2 ;
}
if ( $ script ) {
print $ script $ _ ;
print $ script "\n" ;
}
if ( $ trace ) {
s/\n/GS-----> \n/g ;
print "GS-----> $_\n" ;
}
$ lastlineblank = 0 ;
}
}
unless ( $ lastlineblank ) {
print $ script "\n" if $ script ;
print "GS----->\n" if $ trace ;
}
emit ( '################################################################################' ,
"# End of imports from $file" ,
'################################################################################' ) ;
}
2012-03-19 21:38:24 +01:00
if ( $ ifstack < @ ifstack ) {
$ currentfilename = $ file ;
$ currentlinenumber = 'EOF' ;
fatal_error "Missing ?ENDIF to match the ?IF at line $ifstack[-1]->[3]" ;
} else {
$ ifstack = $ save_ifstack ;
}
close IF ;
2011-01-16 00:43:45 +01:00
}
}
2009-02-22 18:30:14 +01:00
#
# The following two functions allow module clients to nest opens. This happens frequently
2010-12-28 22:51:45 +01:00
# in the Rules module.
2009-02-22 18:30:14 +01:00
#
2015-08-15 01:11:41 +02:00
sub push_open ( $;$$$$ ) {
my ( $ file , $ max , $ ca , $ nc , $ cf ) = @ _ ;
2012-12-24 22:35:42 +01:00
push_include ;
2013-11-18 15:57:54 +01:00
clear_section_function ;
2009-02-22 18:30:14 +01:00
my @ a = @ includestack ;
push @ openstack , \ @ a ;
@ includestack = ( ) ;
$ currentfile = undef ;
2015-08-15 01:11:41 +02:00
open_file ( $ file , $ max , $ comments_allowed || $ ca , $ nc , $ cf ) ;
2009-02-22 18:30:14 +01:00
}
sub pop_open () {
@ includestack = @ { pop @ openstack } ;
pop_include ;
}
2009-08-23 19:43:01 +02:00
#
# This function is called by in-line PERL to generate a line of input for the current file.
# If the in-line PERL returns an indication of success, then the generated lines will be
# processed as regular file input.
#
2009-02-22 18:30:14 +01:00
sub shorewall {
2009-10-06 00:43:29 +02:00
unless ( $ perlscript ) {
2009-02-22 18:30:14 +01:00
fatal_error "shorewall() may not be called in this context" unless $ currentfile ;
$ dir || = '/tmp/' ;
eval {
2009-10-06 00:43:29 +02:00
( $ perlscript , $ perlscriptname ) = tempfile ( 'perlscriptXXXX' , DIR = > $ dir ) ;
2009-02-22 18:30:14 +01:00
} ;
fatal_error "Unable to create temporary file in directory $dir" if $@ ;
}
2009-10-06 00:43:29 +02:00
print $ perlscript "@_\n" ;
2009-02-22 18:30:14 +01:00
}
#
2009-08-20 23:32:15 +02:00
# We don't announce that we are checking/compiling a file until we determine that the file contains
2009-02-22 18:30:14 +01:00
# at least one non-blank, non-commentary line.
#
# The argument to this function may be either a scalar or a function reference. When the first
2009-08-20 23:32:15 +02:00
# non-blank/non-commentary line is reached:
2009-02-22 18:30:14 +01:00
#
# - if a function reference was passed to first_entry(), that function is called
# - otherwise, the argument to first_entry() is passed to progress_message2().
#
# We do this processing in read_a_line() rather than in the higher-level routines because
# Embedded Shell/Perl scripts are processed out of read_a_line(). If we were to defer announcement
2009-08-20 23:32:15 +02:00
# until we get back to the caller of read_a_line(), we could issue error messages about parsing and
2009-02-22 18:30:14 +01:00
# running scripts in the file before we'd even indicated that we are processing it.
#
2012-12-22 20:57:25 +01:00
sub first_entry ( $ ) {
$ first_entry = shift ;
2009-02-22 18:30:14 +01:00
my $ reftype = reftype $ first_entry ;
2012-04-11 23:27:48 +02:00
assert ( $ reftype eq 'CODE' ) if $ reftype ;
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
2012-04-14 17:04:28 +02:00
sub read_a_line ($) ;
2012-04-07 16:42:27 +02:00
2009-02-22 18:30:14 +01:00
sub embedded_shell ( $ ) {
my $ multiline = shift ;
fatal_error "INCLUDEs nested too deeply" if @ includestack >= 4 ;
my ( $ command , $ linenumber ) = ( "/bin/sh -c '$currentline" , $ currentlinenumber ) ;
2014-02-25 22:21:23 +01:00
$ directive_callback - > ( 'SHELL' , $ currentline ) if $ directive_callback ;
2009-02-22 18:30:14 +01:00
if ( $ multiline ) {
#
# Multi-line script
#
fatal_error "Invalid BEGIN SHELL directive" unless $ currentline =~ /^\s*$/ ;
$ command . = "\n" ;
my $ last = 0 ;
2012-04-11 02:01:38 +02:00
while ( read_a_line ( PLAIN_READ ) ) {
2014-02-25 22:21:23 +01:00
$ directive_callback - > ( 'SHELL' , $ currentline ) if $ directive_callback ;
2013-06-20 19:39:39 +02:00
last if $ last = $ currentline =~ s/^\s*\??END(\s+SHELL)?\s*(?:;\s*)?$//i ;
2012-04-08 21:17:00 +02:00
$ command . = "$currentline\n" ;
2009-02-22 18:30:14 +01:00
}
fatal_error ( "Missing END SHELL" ) unless $ last ;
2012-04-07 16:16:17 +02:00
fatal_error ( "Invalid END SHELL directive" ) unless $ currentline =~ /^\s*$/ ;
2009-02-22 18:30:14 +01:00
}
$ command . = q( ' ) ;
2012-12-24 22:35:42 +01:00
push_include ;
2009-02-22 18:30:14 +01:00
$ currentfile = undef ;
open $ currentfile , '-|' , $ command or fatal_error qq( Shell Command failed ) ;
$ currentfilename = "SHELL\@$currentfilename:$currentlinenumber" ;
$ currentline = '' ;
$ currentlinenumber = 0 ;
2012-03-19 15:38:52 +01:00
$ ifstack = @ ifstack ;
2009-02-22 18:30:14 +01:00
}
sub embedded_perl ( $ ) {
my $ multiline = shift ;
2011-12-17 19:09:23 +01:00
my ( $ command , $ linenumber ) = ( qq( package Shorewall::User;\nno strict;\nuse Shorewall::Config ( qw/shorewall/ ) ;\n# line $currentlinenumber "$currentfilename"\n$currentline ) , $ currentlinenumber ) ;
2009-02-22 18:30:14 +01:00
2014-02-25 22:21:23 +01:00
$ directive_callback - > ( 'PERL' , $ currentline ) if $ directive_callback ;
2009-02-22 18:30:14 +01:00
if ( $ multiline ) {
#
# Multi-line script
#
fatal_error "Invalid BEGIN PERL directive" unless $ currentline =~ /^\s*$/ ;
$ command . = "\n" ;
my $ last = 0 ;
2012-04-11 02:01:38 +02:00
while ( read_a_line ( PLAIN_READ ) ) {
2014-02-25 22:21:23 +01:00
$ directive_callback - > ( 'PERL' , $ currentline ) if $ directive_callback ;
2013-06-20 19:39:39 +02:00
last if $ last = $ currentline =~ s/^\s*\??END(\s+PERL)?\s*(?:;\s*)?//i ;
2012-04-08 21:17:00 +02:00
$ command . = "$currentline\n" ;
2009-02-22 18:30:14 +01:00
}
fatal_error ( "Missing END PERL" ) unless $ last ;
2012-04-07 16:16:17 +02:00
fatal_error ( "Invalid END PERL directive" ) unless $ currentline =~ /^\s*$/ ;
2012-06-05 18:02:12 +02:00
} else {
$ currentline = '' ;
2009-02-22 18:30:14 +01:00
}
2012-05-16 01:38:56 +02:00
$ embedded + + ;
2009-02-22 18:30:14 +01:00
unless ( my $ return = eval $ command ) {
2012-04-06 17:00:20 +02:00
#
# Perl found the script offensive or the script itself died
#
2009-02-22 18:30:14 +01:00
if ( $@ ) {
$@ =~ s/, <\$currentfile> line \d+//g ;
fatal_error1 "$@" ;
}
unless ( defined $ return ) {
2009-08-20 23:32:15 +02:00
fatal_error "Perl Script failed: $!" if $! ;
2009-02-22 18:30:14 +01:00
fatal_error "Perl Script failed" ;
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
fatal_error "Perl Script Returned False" ;
}
2012-05-16 01:38:56 +02:00
$ embedded - - ;
2009-10-06 00:43:29 +02:00
if ( $ perlscript ) {
2009-02-22 18:30:14 +01:00
fatal_error "INCLUDEs nested too deeply" if @ includestack >= 4 ;
2011-07-02 17:10:43 +02:00
assert ( close $ perlscript ) ;
2009-02-22 18:30:14 +01:00
2009-10-06 00:43:29 +02:00
$ perlscript = undef ;
2009-02-22 18:30:14 +01:00
2012-12-24 22:35:42 +01:00
push_include ;
2009-02-22 18:30:14 +01:00
$ currentfile = undef ;
2009-10-06 00:43:29 +02:00
open $ currentfile , '<' , $ perlscriptname or fatal_error "Unable to open Perl Script $perlscriptname" ;
2009-02-22 18:30:14 +01:00
2009-10-06 00:43:29 +02:00
push @ tempfiles , $ perlscriptname unless unlink $ perlscriptname ; #unlink fails on Cygwin
2009-02-22 18:30:14 +01:00
2009-10-06 00:43:29 +02:00
$ perlscriptname = '' ;
2009-02-22 18:30:14 +01:00
$ currentfilename = "PERL\@$currentfilename:$linenumber" ;
$ currentline = '' ;
$ currentlinenumber = 0 ;
2012-03-19 15:38:52 +01:00
$ ifstack = @ ifstack ;
2009-02-22 18:30:14 +01:00
}
}
2013-04-09 02:30:00 +02:00
#
# Return inline matches
#
2013-12-16 21:31:35 +01:00
sub fetch_inline_matches () {
2013-04-26 18:09:08 +02:00
"$inline_matches " ;
2013-04-09 02:30:00 +02:00
}
2013-07-10 22:27:58 +02:00
sub set_inline_matches ( $ ) {
$ inline_matches = $ _ [ 0 ] ;
}
2010-12-25 23:48:14 +01:00
#
2013-01-29 01:55:54 +01:00
# Push/pop acton params
2010-12-25 23:48:14 +01:00
#
2013-01-29 01:55:54 +01:00
sub push_action_params ( $$$$$$ ) {
my ( $ action , $ chainref , $ parms , $ loglevel , $ logtag , $ caller ) = @ _ ;
2013-01-19 19:52:11 +01:00
my @ parms = ( undef , split_list3 ( $ parms , 'parameter' ) ) ;
2013-01-18 23:54:57 +01:00
2013-01-19 19:52:11 +01:00
$ actparms { modified } = $ parmsmodified ;
2013-01-18 23:54:57 +01:00
my % oldparms = % actparms ;
2013-01-19 19:52:11 +01:00
$ parmsmodified = 0 ;
2010-12-25 23:48:14 +01:00
2012-12-03 21:31:47 +01:00
% actparms = ( ) ;
2011-07-02 01:23:39 +02:00
2013-01-19 19:52:11 +01:00
for ( my $ i = 1 ; $ i < @ parms ; $ i + + ) {
my $ val = $ parms [ $ i ] ;
2011-07-02 01:23:39 +02:00
2012-12-03 21:31:47 +01:00
$ actparms { $ i } = $ val eq '-' ? '' : $ val eq '--' ? '-' : $ val ;
2011-07-02 01:23:39 +02:00
}
2010-12-25 23:48:14 +01:00
2013-01-19 19:52:11 +01:00
$ actparms { 0 } = $ chainref ;
2013-01-29 01:55:54 +01:00
$ actparms { action } = $ action ;
2013-01-19 19:52:11 +01:00
$ actparms { loglevel } = $ loglevel ;
$ actparms { logtag } = $ logtag ;
$ actparms { caller } = $ caller ;
$ actparms { disposition } = '' if $ chainref - > { action } ;
2012-12-12 22:13:17 +01:00
#
# The Shorewall variable '@chain' has the non-word charaters removed
#
2013-01-19 19:52:11 +01:00
( $ actparms { chain } = $ chainref - > { name } ) =~ s/[^\w]//g ;
2012-12-03 21:31:47 +01:00
2013-01-18 23:54:57 +01:00
\ % oldparms ;
2010-12-25 23:48:14 +01:00
}
2013-01-18 23:54:57 +01:00
#
# Pop the action parameters using the passed hash reference
# Return true of the popped parameters were modified
#
2011-06-11 16:46:54 +02:00
sub pop_action_params ( $ ) {
2013-01-19 19:52:11 +01:00
my $ oldparms = shift ;
% actparms = %$ oldparms ;
my $ return = $ parmsmodified ;
( $ parmsmodified ) = delete $ actparms { modified } ;
2013-01-18 23:54:57 +01:00
$ return ;
2010-12-25 23:48:14 +01:00
}
2011-06-11 16:46:54 +02:00
sub default_action_params {
2011-07-03 16:22:29 +02:00
my $ action = shift ;
my ( $ val , $ i ) ;
2011-06-11 02:05:09 +02:00
2011-07-03 16:22:29 +02:00
for ( $ i = 1 ; 1 ; $ i + + ) {
2011-06-11 02:05:09 +02:00
last unless defined ( $ val = shift ) ;
2012-12-03 21:31:47 +01:00
my $ curval = $ actparms { $ i } ;
$ actparms { $ i } = $ val unless supplied ( $ curval ) ;
2011-06-11 02:05:09 +02:00
}
2011-07-03 16:22:29 +02:00
2012-12-03 21:31:47 +01:00
fatal_error "Too Many arguments to action $action" if defined $ actparms { $ i } ;
2011-06-11 02:05:09 +02:00
}
2011-06-22 17:27:01 +02:00
sub get_action_params ( $ ) {
my $ num = shift ;
2011-06-25 20:39:13 +02:00
fatal_error "Invalid argument to get_action_params()" unless $ num =~ /^\d+$/ && $ num > 0 ;
2011-06-22 17:27:01 +02:00
2011-07-03 17:47:53 +02:00
my @ return ;
for ( my $ i = 1 ; $ i <= $ num ; $ i + + ) {
2012-12-03 21:31:47 +01:00
my $ val = $ actparms { $ i } ;
2011-07-03 17:47:53 +02:00
push @ return , defined $ val ? $ val eq '-' ? '' : $ val eq '--' ? '-' : $ val : $ val ;
}
@ return ;
2011-06-11 17:33:21 +02:00
}
2013-01-18 22:06:55 +01:00
#
# Returns the Level and Tag for the current action chain
#
sub get_action_logging () {
@ actparms { 'loglevel' , 'logtag' } ;
}
2011-07-02 16:02:18 +02:00
sub get_action_chain () {
2012-12-03 21:31:47 +01:00
$ actparms { 0 } ;
2011-07-02 01:21:36 +02:00
}
2013-01-19 19:52:11 +01:00
sub get_action_chain_name () {
$ actparms { chain } ;
}
2013-07-10 22:27:58 +02:00
sub set_action_name_to_caller () {
$ actparms { chain } = $ actparms { caller } ;
}
2013-01-19 19:52:11 +01:00
sub get_action_disposition () {
$ actparms { disposition } ;
}
2013-07-10 22:27:58 +02:00
sub set_action_disposition ($) {
$ actparms { disposition } = $ _ [ 0 ] ;
}
2011-06-11 17:33:21 +02:00
sub set_action_param ( $$ ) {
my $ i = shift ;
2011-06-25 20:39:13 +02:00
fatal_error "Parameter numbers must be numeric" unless $ i =~ /^\d+$/ && $ i > 0 ;
2012-12-03 21:31:47 +01:00
$ actparms { $ i } = shift ;
2011-06-11 16:49:57 +02:00
}
2011-06-26 06:08:32 +02:00
#
2012-12-04 00:33:33 +01:00
# Expand Shell Variables in the passed buffer using %actparms, %params, %shorewallrc1 and %config,
2011-06-26 06:08:32 +02:00
#
2012-04-01 22:19:38 +02:00
sub expand_variables ( \$ ) {
2011-06-26 15:50:22 +02:00
my ( $ lineref , $ count ) = ( $ _ [ 0 ] , 0 ) ;
2012-12-12 22:13:17 +01:00
my $ chain = $ actparms { chain } ;
2012-12-04 17:49:59 +01:00
# $1 $2 $3 - $4
while ( $$ lineref =~ m ( ^(.*?) \ $( { ) ? ( \ d + | [ a - zA - Z_ ] \ w * ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
2011-06-26 06:55:49 +02:00
2011-06-26 06:08:32 +02:00
my ( $ first , $ var , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
my $ val ;
if ( $ var =~ /^\d+$/ ) {
2012-12-12 22:13:17 +01:00
fatal_error "Action parameters (\$$var) may only be referenced within the body of an action" unless $ chain ;
2013-02-10 16:51:35 +01:00
if ( $ config { IGNOREUNKNOWNVARIABLES } ) {
fatal_error "Invalid action parameter (\$$var)" if ( length ( $ var ) > 1 && $ var =~ /^0/ ) ;
} else {
2012-12-12 22:13:17 +01:00
fatal_error "Undefined parameter (\$$var)" unless ( defined $ actparms { $ var } &&
( length ( $ var ) == 1 ||
$ var !~ /^0/ ) ) ;
}
2012-12-03 21:31:47 +01:00
$ val = $ var ? $ actparms { $ var } : $ actparms { 0 } - > { name } ;
2012-12-04 17:49:25 +01:00
} elsif ( exists $ variables { $ var } ) {
$ val = $ variables { $ var } ;
2012-12-03 21:31:47 +01:00
} elsif ( exists $ actparms { $ var } ) {
$ val = $ actparms { $ var } ;
2011-12-15 21:52:22 +01:00
} else {
2012-12-12 20:51:31 +01:00
fatal_error "Undefined shell variable (\$$var)" unless $ config { IGNOREUNKNOWNVARIABLES } || exists $ config { $ var } ;
2012-12-04 02:18:21 +01:00
}
$ val = '' unless defined $ val ;
$$ lineref = join ( '' , $ first , $ val , $ rest ) ;
fatal_error "Variable Expansion Loop" if + + $ count > 100 ;
}
2012-12-12 20:46:38 +01:00
2014-08-20 20:25:49 +02:00
if ( $ chain ) {
2014-08-04 00:11:25 +02:00
#
2014-08-20 20:25:49 +02:00
# We're in an action body -- allow escaping at signs (@) for u32
2014-08-04 00:11:25 +02:00
#
$$ lineref =~ s/\\@/??/g ;
2012-12-12 20:46:38 +01:00
# $1 $2 $3 - $4
while ( $$ lineref =~ m ( ^(.*?) \ @ ( { ) ? ( \ d + | [ a - zA - Z_ ] \ w * ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
my ( $ first , $ var , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
2012-12-12 22:13:17 +01:00
my $ val = $ var ? $ actparms { $ var } : $ actparms { chain } ;
2012-12-12 20:46:38 +01:00
$ val = '' unless defined $ val ;
$$ lineref = join ( '' , $ first , $ val , $ rest ) ;
fatal_error "Variable Expansion Loop" if + + $ count > 100 ;
}
2014-08-04 00:11:25 +02:00
2014-08-04 00:29:58 +02:00
$$ lineref =~ s/\?\?/@/g ;
2012-12-12 20:46:38 +01:00
}
2012-12-04 02:18:21 +01:00
}
sub expand_shorewallrc_variables ( \$ ) {
my ( $ lineref , $ count ) = ( $ _ [ 0 ] , 0 ) ;
# $1 $2 $3 - $4
while ( $$ lineref =~ m ( ^(.*?) \ $( { ) ? ( \ d + | [ a - zA - Z ] \ w * ) ( ? ( 2 ) } ) ( . * ) $ ) x ) {
my ( $ first , $ var , $ rest ) = ( $ 1 , $ 3 , $ 4 ) ;
my $ val ;
if ( exists $ shorewallrc { $ var } ) {
$ val = $ shorewallrc { $ var }
2011-06-26 06:08:32 +02:00
}
2011-06-26 06:55:49 +02:00
2011-06-26 06:08:32 +02:00
$ val = '' unless defined $ val ;
2011-06-26 15:50:22 +02:00
$$ lineref = join ( '' , $ first , $ val , $ rest ) ;
2011-06-26 06:08:32 +02:00
fatal_error "Variable Expansion Loop" if + + $ count > 100 ;
}
}
2012-04-10 00:12:13 +02:00
#
# Handle first-entry processing
#
sub handle_first_entry () {
#
# $first_entry can contain either a function reference or a message. If it
# contains a reference, call the function -- otherwise issue the message
#
2013-01-26 21:18:17 +01:00
my $ entry = $ first_entry ;
2012-04-10 00:12:13 +02:00
$ first_entry = 0 ;
2013-01-26 21:18:17 +01:00
reftype ( $ entry ) ? $ entry - > ( ) : progress_message2 ( $ entry ) ;
2012-04-10 00:12:13 +02:00
}
2009-02-22 18:30:14 +01:00
#
2012-04-25 18:44:08 +02:00
# Read a line from the current include stack. Based on the passed options, it will conditionally:
2009-02-22 18:30:14 +01:00
#
# - Ignore blank or comment-only lines.
# - Remove trailing comments.
# - Handle Line Continuation
# - Handle embedded SHELL and PERL scripts
2010-11-18 15:56:07 +01:00
# - Expand shell variables from %params and %ENV.
2009-02-22 18:30:14 +01:00
# - Handle INCLUDE <filename>
2012-03-16 16:16:12 +01:00
# - Handle ?IF, ?ELSE, ?ENDIF
2009-02-22 18:30:14 +01:00
#
2012-04-14 17:04:28 +02:00
sub read_a_line ($) {
my $ options = $ _ [ 0 ] ;
2010-07-05 22:11:52 +02:00
2009-02-22 18:30:14 +01:00
while ( $ currentfile ) {
$ currentline = '' ;
$ currentlinenumber = 0 ;
while ( <$currentfile> ) {
2012-06-03 17:43:48 +02:00
chomp ;
#
# Handle conditionals
#
2012-12-23 19:49:32 +01:00
if ( /^\s*\?(?:IF|ELSE|ELSIF|ENDIF|SET|RESET|FORMAT|COMMENT)/i ) {
2012-12-05 23:53:03 +01:00
$ omitting = process_compiler_directive ( $ omitting , $ _ , $ currentfilename , $. ) ;
2012-06-03 17:43:48 +02:00
next ;
}
2009-02-22 18:30:14 +01:00
2012-06-03 17:43:48 +02:00
if ( $ omitting ) {
print "OMIT=> $_\n" if $ debug ;
next ;
}
2009-02-22 18:30:14 +01:00
2012-06-03 17:43:48 +02:00
$ currentlinenumber = $. unless $ currentlinenumber ;
2009-02-22 18:30:14 +01:00
#
2009-03-27 17:55:51 +01:00
# Suppress leading whitespace in certain continuation lines
#
2012-04-14 17:04:28 +02:00
s/^\s*// if $ currentline =~ /[,:]$/ && $ options & CONFIG_CONTINUATION ;
2009-03-27 17:55:51 +01:00
#
2012-04-10 01:00:26 +02:00
# If this is a continued line with a trailing comment, remove comment. Note that
# the result will now end in '\'.
2009-09-07 01:17:22 +02:00
#
2012-04-14 17:04:28 +02:00
s/\s*#.*$// if ( $ options & STRIP_COMMENTS ) && /[\\]\s*#.*$/ ;
2009-09-07 01:17:22 +02:00
#
2009-02-22 18:30:14 +01:00
# Continuation
#
2012-04-10 01:00:26 +02:00
chop $ currentline , next if ( $ currentline . = $ _ ) =~ /\\$/ ;
2009-02-22 18:30:14 +01:00
#
# Must check for shell/perl before doing variable expansion
2013-06-20 19:39:39 +02:00
#
2012-04-14 17:04:28 +02:00
if ( $ options & EMBEDDED_ENABLED ) {
2015-01-13 16:04:20 +01:00
if ( $ currentline =~ s/^\s*\??(BEGIN\s+)SHELL\s*;?//i || $ currentline =~ s/^\s*\?SHELL\s*//i || $ currentline =~ s/^\s*SHELL\s+// ) {
2012-04-10 00:12:13 +02:00
handle_first_entry if $ first_entry ;
2010-07-05 22:11:52 +02:00
embedded_shell ( $ 1 ) ;
next ;
}
2009-02-22 18:30:14 +01:00
2013-06-20 19:39:39 +02:00
if ( $ currentline =~ s/^\s*\??(BEGIN\s+)PERL\s*;?//i || $ currentline =~ s/^\s*\??PERL\s*//i ) {
2012-04-10 00:12:13 +02:00
handle_first_entry if $ first_entry ;
2010-07-05 22:11:52 +02:00
embedded_perl ( $ 1 ) ;
next ;
}
2010-09-27 20:16:18 +02:00
}
2012-04-10 00:12:13 +02:00
#
2012-04-14 22:50:59 +02:00
# Now remove concatinated comments if asked
2012-04-10 00:12:13 +02:00
#
2012-04-14 17:04:28 +02:00
$ currentline =~ s/\s*#.*$// if $ options & STRIP_COMMENTS ;
2012-04-14 22:50:59 +02:00
if ( $ options & SUPPRESS_WHITESPACE ) {
#
# Ignore (concatinated) blank lines
#
$ currentline = '' , $ currentlinenumber = 0 , next if $ currentline =~ /^\s*$/ ;
#
# Eliminate trailing whitespace
#
$ currentline =~ s/\s*$// ;
}
2012-04-10 00:12:13 +02:00
#
# Line not blank -- Handle any first-entry message/capabilities check
#
handle_first_entry if $ first_entry ;
2010-07-05 22:11:52 +02:00
#
2012-12-03 21:31:47 +01:00
# Expand Shell Variables using %params and %actparms
2010-07-05 22:11:52 +02:00
#
2012-04-14 17:04:28 +02:00
expand_variables ( $ currentline ) if $ options & EXPAND_VARIABLES ;
2011-06-26 06:55:49 +02:00
2012-04-14 17:04:28 +02:00
if ( ( $ options & DO_INCLUDE ) && $ currentline =~ /^\s*\??INCLUDE\s/ ) {
2009-02-22 18:30:14 +01:00
2010-07-05 22:11:52 +02:00
my @ line = split ' ' , $ currentline ;
2009-02-22 18:30:14 +01:00
2010-07-05 22:11:52 +02:00
fatal_error "Invalid INCLUDE command" if @ line != 2 ;
fatal_error "INCLUDEs/Scripts nested too deeply" if @ includestack >= 4 ;
2009-02-22 18:30:14 +01:00
2010-07-05 22:11:52 +02:00
my $ filename = find_file $ line [ 1 ] ;
2009-02-22 18:30:14 +01:00
2010-07-05 22:11:52 +02:00
fatal_error "INCLUDE file $filename not found" unless - f $ filename ;
fatal_error "Directory ($filename) not allowed in INCLUDE" if - d _ ;
2009-02-22 18:30:14 +01:00
2010-07-05 22:11:52 +02:00
if ( - s _ ) {
2012-12-24 22:35:42 +01:00
push_include ;
2010-07-05 22:11:52 +02:00
$ currentfile = undef ;
do_open_file $ filename ;
2009-02-22 18:30:14 +01:00
} else {
2010-07-05 22:11:52 +02:00
$ currentlinenumber = 0 ;
2009-02-22 18:30:14 +01:00
}
2010-07-05 22:11:52 +02:00
$ currentline = '' ;
2013-11-27 16:53:33 +01:00
} elsif ( ( $ options & DO_SECTION ) && $ currentline =~ /^\s*\?SECTION\s+(.*)/i ) {
2013-11-18 15:57:54 +01:00
my $ sectionname = $ 1 ;
fatal_error "Invalid SECTION name ($sectionname)" unless $ sectionname =~ /^[-_\da-zA-Z]+$/ ;
fatal_error "This file does not allow ?SECTION" unless $ section_function ;
$ section_function - > ( $ sectionname ) ;
2014-02-25 21:48:25 +01:00
$ directive_callback - > ( 'SECTION' , $ currentline ) if $ directive_callback ;
2013-11-18 15:57:54 +01:00
$ currentline = '' ;
2010-07-05 22:11:52 +02:00
} else {
2012-04-14 17:04:28 +02:00
fatal_error "Non-ASCII gunk in file" if ( $ options && CHECK_GUNK ) && $ currentline =~ /[^\s[:print:]]/ ;
2010-07-05 22:11:52 +02:00
print "IN===> $currentline\n" if $ debug ;
return 1 ;
2009-02-22 18:30:14 +01:00
}
}
close_file ;
}
}
2012-09-04 15:59:16 +02:00
sub process_shorewallrc ( $$ ) {
my ( $ shorewallrc , $ product ) = @ _ ;
2012-03-24 21:05:39 +01:00
2012-09-04 15:59:16 +02:00
$ shorewallrc { PRODUCT } = $ product ;
2012-03-25 16:25:15 +02:00
2012-04-01 19:47:24 +02:00
if ( open_file $ shorewallrc ) {
2012-04-11 02:01:38 +02:00
while ( read_a_line ( STRIP_COMMENTS | SUPPRESS_WHITESPACE | CHECK_GUNK ) ) {
2012-03-24 21:05:39 +01:00
if ( $ currentline =~ /^([a-zA-Z]\w*)=(.*)$/ ) {
my ( $ var , $ val ) = ( $ 1 , $ 2 ) ;
2012-03-25 06:26:20 +02:00
$ val = $ 1 if $ val =~ /^\"([^\"]*)\"$/ ;
2012-12-04 02:18:21 +01:00
expand_shorewallrc_variables ( $ val ) if supplied $ val ;
2012-03-25 06:26:20 +02:00
$ shorewallrc { $ var } = $ val ;
2012-03-24 21:05:39 +01:00
} else {
fatal_error "Unrecognized shorewallrc entry" ;
}
}
2012-04-01 19:47:24 +02:00
} else {
fatal_error "Failed to open $shorewallrc: $!" ;
2012-03-24 21:05:39 +01:00
}
2012-09-09 22:12:32 +02:00
if ( supplied $ shorewallrc { VARDIR } ) {
if ( ! supplied $ shorewallrc { VARLIB } ) {
$ shorewallrc { VARLIB } = $ shorewallrc { VARDIR } ;
$ shorewallrc { VARDIR } = "$shorewallrc{VARLIB}/$product" ;
}
} elsif ( supplied $ shorewallrc { VARLIB } ) {
$ shorewallrc { VARDIR } = "$shorewallrc{VARLIB}/$product" unless supplied $ shorewallrc { VARDIR } ;
}
2012-03-24 21:05:39 +01:00
}
2009-02-22 18:30:14 +01:00
#
# Provide the passed default value for the passed configuration variable
#
sub default ( $$ ) {
my ( $ var , $ val ) = @ _ ;
2011-06-12 01:14:31 +02:00
$ config { $ var } = $ val unless supplied ( $ config { $ var } ) ;
2009-02-22 18:30:14 +01:00
}
#
# Provide a default value for a yes/no configuration variable.
#
2014-09-27 16:57:46 +02:00
sub default_yes_no ( $$;$ ) {
my ( $ var , $ val , $ other ) = @ _ ;
2014-09-28 00:06:18 +02:00
my $ result = 1 ;
2009-02-22 18:30:14 +01:00
2010-06-24 22:58:46 +02:00
my $ curval = $ config { $ var } ;
2009-02-22 18:30:14 +01:00
2011-06-12 01:14:31 +02:00
if ( supplied $ curval ) {
2010-06-24 22:58:46 +02:00
$ curval = lc $ curval ;
2009-02-22 18:30:14 +01:00
if ( $ curval eq 'no' ) {
$ config { $ var } = '' ;
2014-09-28 00:06:18 +02:00
} elsif ( defined ( $ other ) ) {
if ( $ other eq '*' ) {
if ( $ curval eq 'yes' ) {
$ config { $ var } = 'Yes' ;
} else {
$ result = 0 ;
}
} elsif ( $ curval eq $ other ) {
#
# Downshift value for later comparison
#
$ config { $ var } = $ curval ;
}
2009-02-22 18:30:14 +01:00
} else {
2011-06-18 22:03:55 +02:00
fatal_error "Invalid value for $var ($curval)" unless $ curval eq 'yes' ;
2014-09-27 16:57:46 +02:00
#
# Make Case same as default
#
$ config { $ var } = 'Yes' ;
2009-02-22 18:30:14 +01:00
}
} else {
$ config { $ var } = $ val ;
}
2014-09-28 00:06:18 +02:00
$ result ;
2009-02-22 18:30:14 +01:00
}
sub default_yes_no_ipv4 ( $$ ) {
my ( $ var , $ val ) = @ _ ;
default_yes_no ( $ var , $ val ) ;
warning_message "$var=Yes is ignored for IPv6" if $ family == F_IPV6 && $ config { $ var } ;
}
2010-01-11 23:16:03 +01:00
sub numeric_option ( $$$ ) {
my ( $ option , $ default , $ min ) = @ _ ;
my $ value = $ config { $ option } ;
my $ val = $ default ;
2010-06-07 16:30:56 +02:00
2011-06-12 01:14:31 +02:00
if ( supplied $ value ) {
2010-01-11 23:16:03 +01:00
$ val = numeric_value $ value ;
fatal_error "Invalid value ($value) for '$option'" unless defined $ val && $ val <= 32 ;
}
$ val = $ min if $ val < $ min ;
$ config { $ option } = $ val ;
}
sub make_mask ( $ ) {
0xffffffff >> ( 32 - $ _ [ 0 ] ) ;
2010-06-07 16:30:56 +02:00
}
2009-02-22 18:30:14 +01:00
my @ suffixes = qw( group range threshold nlgroup cprange qthreshold ) ;
#
# Validate a log level -- Drop the trailing '!' and translate to numeric value if appropriate"
#
2013-09-07 01:00:15 +02:00
sub level_error ( $;$ ) {
my ( $ level , $ option ) = @ _ ;
if ( $ option ) {
fatal_error "Invalid log level ($level) for option $option" ;
} else {
fatal_error "Invalid log level ($_[0])" ;
}
2009-02-22 18:30:14 +01:00
}
2012-05-24 22:54:59 +02:00
my % logoptions = ( tcp_sequence = > '--log-tcp-sequence' ,
ip_options = > '--log-ip-options' ,
tcp_options = > '--log-tcp-options' ,
uid = > '--log-uid' ,
macdecode = > '--log-macdecode' ,
#
# Because a level can pass through validate_level() more than once,
# the full option names are also included here.
#
'--log-tcp-sequence' = > '--log-tcp-sequence' ,
'--log-ip-options' = > '--log-ip-options' ,
'--log-tcp-options' = > '--log-tcp-options' ,
'--log-uid' = > '--log-uid' ,
'--log-macdecode' = > '--log-macdecode' ,
) ;
2013-09-07 01:00:15 +02:00
sub validate_level ( $;$ ) {
my ( $ rawlevel , $ option ) = @ _ ;
2009-02-22 18:30:14 +01:00
my $ level = uc $ rawlevel ;
2011-06-12 01:14:31 +02:00
if ( supplied ( $ level ) ) {
2011-11-16 01:41:32 +01:00
$ level =~ s/!$// ;
2011-11-12 23:10:48 +01:00
my $ value = $ level ;
my $ qualifier ;
2009-06-25 22:50:27 +02:00
2011-11-12 23:10:48 +01:00
unless ( $ value =~ /^[0-7]$/ ) {
2012-05-24 22:54:59 +02:00
} if ( $ value =~ /^([0-7])(.*)$/ ) {
$ value = $ 1 ;
$ qualifier = $ 2 ;
} elsif ( $ value =~ /^([A-Za-z0-7]+)(.*)$/ ) {
2013-09-07 01:00:15 +02:00
level_error ( $ level , $ option ) unless defined ( $ value = $ validlevels { $ 1 } ) ;
2012-05-24 22:54:59 +02:00
$ qualifier = $ 2 ;
2009-06-25 22:50:27 +02:00
}
2011-11-12 23:10:48 +01:00
if ( $ value =~ /^[0-7]$/ ) {
#
# Syslog Level
#
2012-05-24 22:54:59 +02:00
if ( supplied $ qualifier ) {
my $ options = '' ;
my % options ;
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) unless $ qualifier =~ /^\((.*)\)$/ ;
2012-05-24 22:54:59 +02:00
for ( split_list lc $ 1 , "log options" ) {
my $ option = $ logoptions { $ _ } ;
fatal_error "Unknown LOG option ($_)" unless $ option ;
unless ( $ options { $ option } ) {
if ( $ options ) {
$ options = join ( ',' , $ options , $ option ) ;
} else {
$ options = $ option ;
}
$ options { $ option } = 1 ;
}
}
$ value . = "($options)" if $ options ;
}
2011-11-12 23:10:48 +01:00
2013-09-07 01:00:15 +02:00
if ( $ option ) {
require_capability ( 'LOG_TARGET' , "Log level $level for option $option" , 's' ) ;
} else {
require_capability ( 'LOG_TARGET' , "Log level $level" , 's' ) ;
}
2011-11-12 23:10:48 +01:00
return $ value ;
2009-06-25 22:50:27 +02:00
}
2009-02-22 18:30:14 +01:00
2011-11-12 23:10:48 +01:00
return '' unless $ value ;
2013-09-07 01:00:15 +02:00
if ( $ option ) {
require_capability ( "${value}_TARGET" , "Log level $level for option $option" , 's' ) ;
} else {
require_capability ( "${value}_TARGET" , "Log level $level" , 's' ) ;
}
2011-11-12 23:10:48 +01:00
if ( $ value =~ /^(NFLOG|ULOG)$/ ) {
my $ olevel = $ value ;
if ( $ qualifier =~ /^[(](.*)[)]$/ ) {
my @ options = split /,/ , $ 1 ;
my $ prefix = lc $ olevel ;
my $ index = $ prefix eq 'ulog' ? 3 : 0 ;
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) if @ options > 3 ;
2009-02-22 18:30:14 +01:00
2011-11-12 23:10:48 +01:00
for ( @ options ) {
if ( supplied ( $ _ ) ) {
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) unless /^\d+/ ;
2011-11-12 23:10:48 +01:00
$ olevel . = " --${prefix}-$suffixes[$index] $_" ;
}
2009-02-22 18:30:14 +01:00
2011-11-12 23:10:48 +01:00
$ index + + ;
2009-02-22 18:30:14 +01:00
}
2011-11-12 23:10:48 +01:00
} elsif ( $ qualifier =~ /^ --/ ) {
return $ rawlevel ;
2011-11-13 14:58:59 +01:00
} else {
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) if $ qualifier ;
2009-02-22 18:30:14 +01:00
}
return $ olevel ;
}
2011-11-12 23:10:48 +01:00
#
# Must be LOGMARK
#
my $ sublevel ;
2011-07-19 15:53:49 +02:00
2011-11-12 23:10:48 +01:00
if ( supplied $ qualifier ) {
2011-11-13 15:19:40 +01:00
return $ rawlevel if $ qualifier =~ /^ --/ ;
2011-11-17 16:22:07 +01:00
if ( $ qualifier =~ /[(](.+)[)]$/ ) {
2011-11-12 23:10:48 +01:00
$ sublevel = $ 1 ;
2011-07-19 15:53:49 +02:00
2011-07-19 20:57:12 +02:00
$ sublevel = $ validlevels { $ sublevel } unless $ sublevel =~ /^[0-7]$/ ;
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) unless defined $ sublevel && $ sublevel =~ /^[0-7]$/ ;
2011-07-19 20:57:12 +02:00
} else {
2013-09-07 01:00:15 +02:00
level_error ( $ rawlevel , $ option ) ;
2011-07-19 20:57:12 +02:00
}
2011-11-12 23:10:48 +01:00
} else {
$ sublevel = 6 ; # info
2009-04-12 17:22:19 +02:00
}
2011-11-12 23:10:48 +01:00
return "LOGMARK --log-level $sublevel" ;
2009-02-22 18:30:14 +01:00
}
'' ;
}
#
# Validate a log level and supply default
#
sub default_log_level ( $$ ) {
my ( $ level , $ default ) = @ _ ;
my $ value = $ config { $ level } ;
2011-06-12 01:14:31 +02:00
unless ( supplied $ value ) {
2013-09-07 01:00:15 +02:00
$ config { $ level } = validate_level $ default , $ level ;
2009-02-22 18:30:14 +01:00
} else {
2015-09-07 01:08:59 +02:00
( $ value , my $ tag ) = split ( ':' , $ value , 2 ) ;
2013-09-07 01:00:15 +02:00
$ config { $ level } = validate_level $ value , $ level ;
2015-09-07 01:08:59 +02:00
if ( supplied $ tag ) {
my $ tag_name = $ level ;
$ tag_name =~ s/_LEVEL/_TAG/ ;
$ globals { $ tag_name } = $ tag ;
}
2009-02-22 18:30:14 +01:00
}
}
#
# Check a tri-valued variable
#
sub check_trivalue ( $$ ) {
my ( $ var , $ default ) = @ _ ;
2011-02-12 01:53:49 +01:00
my $ val = $ config { $ var } ;
2009-02-22 18:30:14 +01:00
if ( defined $ val ) {
2011-02-12 01:53:49 +01:00
$ val = lc $ val ;
2009-02-22 18:30:14 +01:00
if ( $ val eq 'yes' || $ val eq 'on' ) {
$ config { $ var } = 'on' ;
} elsif ( $ val eq 'no' || $ val eq 'off' ) {
$ config { $ var } = 'off' ;
} elsif ( $ val eq 'keep' ) {
$ config { $ var } = '' ;
} elsif ( $ val eq '' ) {
$ config { $ var } = $ default
} else {
fatal_error "Invalid value ($val) for $var" ;
}
} else {
2011-02-20 00:46:06 +01:00
$ config { $ var } = $ default
2009-02-22 18:30:14 +01:00
}
}
#
# Produce a report of the detected capabilities
#
sub report_capability ( $ ) {
my $ cap = $ _ [ 0 ] ;
print " $capdesc{$cap}: " ;
2009-12-19 21:42:39 +01:00
if ( $ cap eq 'CAPVERSION' || $ cap eq 'KERNELVERSION' ) {
my $ version = $ capabilities { $ cap } ;
2009-02-22 18:30:14 +01:00
printf "%d.%d.%d\n" , int ( $ version / 10000 ) , int ( ( $version % 10000 ) / 100 ) , int ( $ version % 100 ) ;
} else {
print $ capabilities { $ cap } ? "Available\n" : "Not Available\n" ;
}
}
sub report_capabilities () {
2009-08-22 16:57:55 +02:00
if ( $ verbosity > 1 ) {
2009-02-22 18:30:14 +01:00
print "Shorewall has detected the following capabilities:\n" ;
for my $ cap ( sort { $ capdesc { $ a } cmp $ capdesc { $ b } } keys % capabilities ) {
report_capability $ cap ;
}
}
}
#
# Search the current PATH for the passed executable
#
sub which ( $ ) {
my $ prog = $ _ [ 0 ] ;
for ( split /:/ , $ config { PATH } ) {
return "$_/$prog" if - x "$_/$prog" ;
}
'' ;
}
#
# Load the kernel modules defined in the 'modules' file.
#
sub load_kernel_modules ( ) {
my $ moduleloader = which ( 'modprobe' ) || ( which 'insmod' ) ;
my $ modulesdir = $ config { MODULESDIR } ;
unless ( $ modulesdir ) {
my $ uname = `uname -r` ;
fatal_error "The command 'uname -r' failed" unless $? == 0 ;
chomp $ uname ;
2011-01-29 21:42:22 +01:00
$ modulesdir = "/lib/modules/$uname/kernel/net/ipv4/netfilter:/lib/modules/$uname/kernel/net/ipv6/netfilter:/lib/modules/$uname/kernel/net/netfilter:/lib/modules/$uname/extra:/lib/modules/$uname/extra/ipset" ;
2009-02-22 18:30:14 +01:00
}
2012-04-24 23:52:57 +02:00
my @ moduledirectories ;
2009-02-22 18:30:14 +01:00
2011-01-29 21:42:22 +01:00
for ( split /:/ , $ modulesdir ) {
push @ moduledirectories , $ _ if - d $ _ ;
}
if ( $ moduleloader && @ moduledirectories && open_file ( $ config { LOAD_HELPERS_ONLY } ? 'helpers' : 'modules' ) ) {
2009-02-22 18:30:14 +01:00
my % loadedmodules ;
$ loadedmodules { $ _ } + + for split_list ( $ config { DONT_LOAD } , 'module' ) ;
2010-03-28 22:09:04 +02:00
progress_message2 "Loading Modules..." ;
2009-02-22 18:30:14 +01:00
open LSMOD , '-|' , 'lsmod' or fatal_error "Can't run lsmod" ;
while ( <LSMOD> ) {
my $ module = ( split ( /\s+/ , $ _ , 2 ) ) [ 0 ] ;
$ loadedmodules { $ module } + + unless $ module eq 'Module'
}
close LSMOD ;
2015-01-27 21:43:42 +01:00
$ config { MODULE_SUFFIX } = 'o gz xz ko o.gz o.xz ko.gz ko.xz' unless $ config { MODULE_SUFFIX } ;
2009-02-22 18:30:14 +01:00
my @ suffixes = split /\s+/ , $ config { MODULE_SUFFIX } ;
2012-04-14 17:04:28 +02:00
while ( read_a_line ( NORMAL_READ ) ) {
2009-02-22 18:30:14 +01:00
fatal_error "Invalid modules file entry" unless ( $ currentline =~ /^loadmodule\s+([a-zA-Z]\w*)\s*(.*)$/ ) ;
my ( $ module , $ arguments ) = ( $ 1 , $ 2 ) ;
unless ( $ loadedmodules { $ module } ) {
for my $ directory ( @ moduledirectories ) {
for my $ suffix ( @ suffixes ) {
my $ modulefile = "$directory/$module.$suffix" ;
if ( - f $ modulefile ) {
if ( $ moduleloader eq 'insmod' ) {
system ( "insmod $modulefile $arguments" ) ;
} else {
system ( "modprobe $module $arguments" ) ;
}
2012-04-24 23:52:57 +02:00
2009-02-22 18:30:14 +01:00
$ loadedmodules { $ module } = 1 ;
}
}
}
}
}
}
}
2009-12-19 21:42:39 +01:00
#
# Get the current kernel version
#
sub determine_kernelversion () {
my $ kernelversion = `uname -r` ;
if ( $ kernelversion =~ /^(\d+)\.(\d+).(\d+)/ ) {
$ capabilities { KERNELVERSION } = sprintf "%d%02d%02d" , $ 1 , $ 2 , $ 3 ;
2011-07-28 02:03:27 +02:00
} elsif ( $ kernelversion =~ /^(\d+)\.(\d+)/ ) {
$ capabilities { KERNELVERSION } = sprintf "%d%02d00" , $ 1 , $ 2 ;
2009-12-19 21:42:39 +01:00
} else {
2010-01-06 17:26:13 +01:00
fatal_error "Unrecognized Kernel Version Format ($kernelversion)" ;
2009-12-19 21:42:39 +01:00
}
}
2009-02-22 18:30:14 +01:00
#
2010-01-29 19:38:22 +01:00
# Capability Reporting and detection.
2009-02-22 18:30:14 +01:00
#
2010-01-25 19:50:49 +01:00
sub Nat_Enabled () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t nat -L -n" ) ;
2010-01-25 19:50:49 +01:00
}
2009-08-15 17:35:54 +02:00
2010-01-25 19:50:49 +01:00
sub Persistent_Snat () {
2013-02-19 00:15:26 +01:00
have_capability ( 'NAT_ENABLED' ) || return '' ;
2009-02-22 18:30:14 +01:00
2010-01-26 00:59:31 +01:00
my $ result = '' ;
2013-02-23 21:59:38 +01:00
my $ address = $ family == F_IPV4 ? '1.2.3.4' : '2001::1' ;
2010-01-26 00:59:31 +01:00
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -t nat -N $sillyname" ) ) {
$ result = qt1 ( "$iptables $iptablesw -t nat -A $sillyname -j SNAT --to-source $address --persistent" ) ;
qt1 ( "$iptables $iptablesw -t nat -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t nat -X $sillyname" ) ;
2010-06-07 16:30:56 +02:00
2010-01-25 19:50:49 +01:00
}
2010-01-26 00:59:31 +01:00
$ result ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2013-02-27 18:25:26 +01:00
sub Masquerade_Tgt () {
have_capability ( 'NAT_ENABLED' ) || return '' ;
my $ result = '' ;
my $ address = $ family == F_IPV4 ? '1.2.3.4' : '2001::1' ;
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -t nat -N $sillyname" ) ) {
$ result = qt1 ( "$iptables $iptablesw -t nat -A $sillyname -j MASQUERADE" ) ;
qt1 ( "$iptables $iptablesw -t nat -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t nat -X $sillyname" ) ;
2013-02-27 18:25:26 +01:00
}
$ result ;
}
2013-03-10 18:07:52 +01:00
sub Udpliteredirect () {
have_capability ( 'NAT_ENABLED' ) || return '' ;
my $ result = '' ;
my $ address = $ family == F_IPV4 ? '1.2.3.4' : '2001::1' ;
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -t nat -N $sillyname" ) ) {
$ result = qt1 ( "$iptables $iptablesw -t nat -A $sillyname -p udplite -m multiport --dports 33 -j REDIRECT --to-port 22" ) ;
qt1 ( "$iptables $iptablesw -t nat -F $sillyname" ) ;
qt1 ( "$iptables $iptablesw -t nat -X $sillyname" ) ;
2013-03-10 18:07:52 +01:00
}
$ result ;
}
2010-01-25 19:50:49 +01:00
sub Mangle_Enabled () {
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -t mangle -L -n" ) ) {
2010-01-25 19:50:49 +01:00
system ( "$iptables -t mangle -N $sillyname" ) == 0 || fatal_error "Cannot Create Mangle chain $sillyname" ;
}
}
2009-03-28 20:21:36 +01:00
2010-01-25 19:50:49 +01:00
sub Conntrack_Match () {
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m conntrack --ctorigdst 192.168.1.1 -j ACCEPT" ) ;
2009-02-22 18:30:14 +01:00
} else {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m conntrack --ctorigdst ::1 -j ACCEPT" ) ;
2009-02-22 18:30:14 +01:00
}
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub New_Conntrack_Match () {
2013-09-04 19:16:36 +02:00
have_capability ( 'CONNTRACK_MATCH' ) && qt1 ( "$iptables $iptablesw -A $sillyname -m conntrack -p tcp --ctorigdstport 22 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Old_Conntrack_Match () {
2013-09-04 19:16:36 +02:00
! qt1 ( "$iptables $iptablesw -A $sillyname -m conntrack ! --ctorigdst 1.2.3.4" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Multiport () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -m multiport --dports 21,22 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Kludgefree1 () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MULTIPORT' ) && qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -m multiport --sports 60 -m multiport --dports 99 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Kludgefree2 () {
2013-09-04 19:16:36 +02:00
have_capability ( 'PHYSDEV_MATCH' ) && qt1 ( "$iptables $iptablesw -A $sillyname -m physdev --physdev-in eth0 -m physdev --physdev-out eth0 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub Kludgefree3 () {
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m iprange --src-range 192.168.1.5-192.168.1.124 -m iprange --dst-range 192.168.1.5-192.168.1.124 -j ACCEPT" ) ;
2009-02-22 18:30:14 +01:00
} else {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m iprange --src-range ::1-::2 -m iprange --dst-range 192.168.1.5-192.168.1.124 -j ACCEPT" ) ;
2009-02-22 18:30:14 +01:00
}
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Kludgefree () {
Kludgefree1 || Kludgefree2 || Kludgefree3 ;
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Xmultiport () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -m multiport --dports 21:22 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2013-03-10 17:04:47 +01:00
sub Emultiport () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p sctp -m multiport --dports 21,22 -j ACCEPT" ) ;
2013-03-10 17:04:47 +01:00
}
2010-01-25 19:50:49 +01:00
sub Policy_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m policy --pol ipsec --mode tunnel --dir in -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub Physdev_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m physdev --physdev-in eth0 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub Physdev_Bridge () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m physdev --physdev-is-bridged --physdev-in eth0 --physdev-out eth1 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub IPRange_Match () {
if ( $ family == F_IPV4 ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m iprange --src-range 192.168.1.5-192.168.1.124 -j ACCEPT" ) ;
2009-12-07 22:51:08 +01:00
} else {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m iprange --src-range ::1-::2 -j ACCEPT" ) ;
2009-12-07 22:51:08 +01:00
}
2010-01-25 19:50:49 +01:00
}
sub Recent_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m recent --update -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2013-10-07 16:54:52 +02:00
sub Reap_Option () {
( have_capability ( 'RECENT_MATCH' ) &&
qt1 ( "$iptables $iptablesw -A $sillyname -m recent --rcheck --seconds 10 --reap" ) ) ;
}
2010-01-25 19:50:49 +01:00
sub Owner_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m owner --uid-owner 0 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2012-03-26 05:18:20 +02:00
sub Owner_Name_Match () {
if ( my $ name = `id -un 2> /dev/null` ) {
2013-06-24 18:51:32 +02:00
chomp $ name ;
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m owner --uid-owner $name -j ACCEPT" ) ;
2012-03-26 05:18:20 +02:00
}
}
2010-01-25 19:50:49 +01:00
sub Connmark_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m connmark --mark 2 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub Xconnmark_Match () {
2013-09-04 19:16:36 +02:00
have_capability ( 'CONNMARK_MATCH' ) && qt1 ( "$iptables $iptablesw -A $sillyname -m connmark --mark 2/0xFF -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-12-07 22:51:08 +01:00
2010-01-25 19:50:49 +01:00
sub Ipp2p_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -m ipp2p --edk -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Old_Ipp2p_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -m ipp2p --ipp2p -j ACCEPT" ) if $ capabilities { IPP2P_MATCH } ;
2010-01-25 19:50:49 +01:00
}
2009-09-23 22:56:31 +02:00
2010-01-25 19:50:49 +01:00
sub Length_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m length --length 10:20 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
sub Enhanced_Reject () {
if ( $ family == F_IPV6 ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j REJECT --reject-with icmp6-adm-prohibited" ) ;
2009-09-23 22:56:31 +02:00
} else {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j REJECT --reject-with icmp-host-prohibited" ) ;
2009-09-23 22:56:31 +02:00
}
2010-01-25 19:50:49 +01:00
}
2009-09-23 22:56:31 +02:00
2010-01-25 19:50:49 +01:00
sub Comments () {
qt1 ( qq( $iptables -A $sillyname -j ACCEPT -m comment --comment "This is a comment" ) ) ;
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Hashlimit_Match () {
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -A $sillyname -m hashlimit --hashlimit-upto 3/min --hashlimit-burst 3 --hashlimit-name $sillyname --hashlimit-mode srcip -j ACCEPT" ) ) {
2010-07-31 16:19:41 +02:00
! ( $ capabilities { OLD_HL_MATCH } = 0 ) ;
} else {
have_capability 'OLD_HL_MATCH' ;
}
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Old_Hashlimit_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m hashlimit --hashlimit 3/min --hashlimit-burst 3 --hashlimit-name $sillyname --hashlimit-mode srcip -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Mark () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j MARK --set-mark 1" ) ;
2010-01-25 19:50:49 +01:00
}
2009-08-20 23:32:15 +02:00
2010-01-25 19:50:49 +01:00
sub Xmark () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MARK' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j MARK --and-mark 0xFF" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Exmark () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MARK' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j MARK --set-mark 1/0xFF" ) ;
2010-01-25 19:50:49 +01:00
}
sub Connmark () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j CONNMARK --save-mark" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Xconnmark () {
2013-09-04 19:16:36 +02:00
have_capability ( 'XCONNMARK_MATCH' ) && have_capability ( 'XMARK' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j CONNMARK --save-mark --mask 0xFF" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2013-04-09 23:04:16 +02:00
sub New_Tos_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -m tos --tos 0x10/0xff" ) ;
2013-04-09 23:04:16 +02:00
}
2010-01-25 19:50:49 +01:00
sub Classify_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j CLASSIFY --set-class 1:1" ) ;
2010-01-25 19:50:49 +01:00
}
sub IPMark_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j IPMARK --addr src" ) ;
2010-01-25 19:50:49 +01:00
}
sub Tproxy_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -p tcp -j TPROXY --on-port 0 --tproxy-mark 1" ) ;
2010-01-25 19:50:49 +01:00
}
sub Mangle_Forward () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -L FORWARD -n" ) ;
2010-01-25 19:50:49 +01:00
}
sub Raw_Table () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t raw -L -n" ) ;
2010-01-25 19:50:49 +01:00
}
2011-08-13 20:14:29 +02:00
sub Rawpost_Table () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t rawpost -L -n" ) ;
2011-08-13 20:14:29 +02:00
}
2010-08-04 06:06:17 +02:00
sub Old_IPSet_Match () {
2010-01-25 19:50:49 +01:00
my $ ipset = $ config { IPSET } || 'ipset' ;
my $ result = 0 ;
2009-02-22 18:30:14 +01:00
2010-06-17 18:31:57 +02:00
$ ipset = which $ ipset unless $ ipset =~ '/' ;
2009-04-18 18:28:25 +02:00
if ( $ ipset && - x $ ipset ) {
qt ( "$ipset -X $sillyname" ) ;
if ( qt ( "$ipset -N $sillyname iphash" ) ) {
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -A $sillyname -m set --set $sillyname src -j ACCEPT" ) ) {
qt1 ( "$iptables $iptablesw -F $sillyname" ) ;
2010-08-04 06:06:17 +02:00
$ result = $ capabilities { IPSET_MATCH } = 1 ;
}
qt ( "$ipset -X $sillyname" ) ;
}
}
$ result ;
}
sub IPSet_Match () {
my $ ipset = $ config { IPSET } || 'ipset' ;
my $ result = 0 ;
2014-07-19 19:22:12 +02:00
my $ fam = $ family == F_IPV4 ? 'inet' : 'inet6' ;
2010-08-04 06:06:17 +02:00
$ ipset = which $ ipset unless $ ipset =~ '/' ;
2014-01-02 18:36:35 +01:00
$ capabilities { IPSET_MATCH_NOMATCH } = $ capabilities { IPSET_MATCH_COUNTERS } = 0 ;
2010-08-04 06:06:17 +02:00
if ( $ ipset && - x $ ipset ) {
qt ( "$ipset -X $sillyname" ) ;
2014-07-20 03:33:02 +02:00
if ( qt ( "$ipset -N $sillyname hash:ip family $fam" ) || qt ( "$ipset -N $sillyname iphash" ) ) {
2013-09-04 19:16:36 +02:00
if ( qt1 ( "$iptables $iptablesw -A $sillyname -m set --match-set $sillyname src -j ACCEPT" ) ) {
2014-07-19 19:22:12 +02:00
$ capabilities { IPSET_MATCH_NOMATCH } = qt1 ( "$iptables $iptablesw -A $sillyname -m set --match-set $sillyname src --return-nomatch -j ACCEPT" ) ;
$ capabilities { IPSET_MATCH_COUNTERS } = qt1 ( "$iptables $iptablesw -A $sillyname -m set --match-set $sillyname src --packets-lt 100 -j ACCEPT" ) ;
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -F $sillyname" ) ;
2010-08-04 06:06:17 +02:00
$ result = ! ( $ capabilities { OLD_IPSET_MATCH } = 0 ) ;
2014-07-19 19:22:12 +02:00
} else {
$ result = have_capability 'OLD_IPSET_MATCH' ;
2009-02-22 18:30:14 +01:00
}
2014-07-19 17:55:02 +02:00
2014-07-19 19:22:12 +02:00
qt ( "$ipset -X $sillyname" ) ;
}
2009-02-22 18:30:14 +01:00
}
2010-01-25 19:50:49 +01:00
$ result ;
}
2014-01-02 18:36:35 +01:00
sub IPSet_Match_Nomatch () {
have_capability 'IPSET_MATCH' && $ capabilities { IPSET_MATCH_NOMATCH } ;
}
sub IPSet_Match_Counters () {
2014-07-19 19:27:29 +02:00
have_capability 'IPSET_MATCH' && $ capabilities { IPSET_MATCH_COUNTERS } ;
2014-01-02 18:36:35 +01:00
}
2011-06-23 15:36:35 +02:00
sub IPSET_V5 () {
2011-06-23 01:43:42 +02:00
my $ ipset = $ config { IPSET } || 'ipset' ;
my $ result = 0 ;
$ ipset = which $ ipset unless $ ipset =~ '/' ;
if ( $ ipset && - x $ ipset ) {
qt ( "$ipset -X $sillyname" ) ;
if ( qt ( "$ipset -N $sillyname hash:ip family inet" ) ) {
$ result = 1 ;
qt ( "$ipset -X $sillyname" ) ;
}
}
$ result ;
}
2010-01-25 19:50:49 +01:00
sub Usepkttype () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m pkttype --pkt-type broadcast -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2010-01-25 19:50:49 +01:00
sub Addrtype () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m addrtype --src-type BROADCAST -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-02-22 18:30:14 +01:00
2014-12-29 00:23:30 +01:00
sub Tarpit_Target () {
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp -j TARPIT" ) ;
}
2010-01-25 19:50:49 +01:00
sub Tcpmss_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1000:1500 -j ACCEPT" ) ;
2010-01-25 19:50:49 +01:00
}
2009-12-19 21:42:39 +01:00
2010-01-25 19:50:49 +01:00
sub Nfqueue_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j NFQUEUE --queue-num 4" ) ;
2009-02-22 18:30:14 +01:00
}
2010-01-25 19:50:49 +01:00
sub Realm_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m realm --realm 1" ) ;
2010-01-25 19:50:49 +01:00
}
2012-08-05 17:08:20 +02:00
sub Helper_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp --dport 21 -m helper --helper ftp" ) ;
2012-08-05 17:08:20 +02:00
}
2012-08-07 00:54:45 +02:00
sub have_helper ( $$$ ) {
my ( $ helper , $ proto , $ port ) = @ _ ;
2012-08-05 17:08:20 +02:00
2013-10-08 18:20:46 +02:00
my $ helper_base = $ helper ;
$ helper_base =~ s/-\d$// ;
$ helper_base = $ helpers_map { $ helper_base } ;
$ helper_base =~ s/_HELPER// ;
$ helper_base =~ s/_/-/ ;
if ( $ helpers_enabled { lc $ helper_base } ) {
2012-08-05 17:08:20 +02:00
if ( have_capability 'CT_TARGET' ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t raw -A $sillyname -p $proto --dport $port -j CT --helper $helper" ) ;
2012-08-05 17:08:20 +02:00
} else {
have_capability 'HELPER_MATCH' ;
}
}
}
2012-08-03 19:53:20 +02:00
sub Amanda_Helper () {
2012-08-07 00:54:45 +02:00
have_helper ( 'amanda' , 'udp' , 10080 ) ;
2012-08-03 19:53:20 +02:00
}
2012-08-07 00:54:45 +02:00
sub FTP0_Helper () {
have_helper ( 'ftp-0' , 'tcp' , 21 ) and $ helpers_aliases { ftp } = 'ftp-0' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub FTP_Helper () {
2013-04-18 19:30:56 +02:00
have_helper ( 'ftp' , 'tcp' , 21 ) || have_capability 'FTP0_HELPER' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub H323_Helpers () {
have_helper ( 'RAS' , 'udp' , 1719 ) ;
2012-08-07 00:54:45 +02:00
}
sub IRC0_Helper () {
have_helper ( 'irc-0' , 'tcp' , 6667 ) and $ helpers_aliases { irc } = 'irc-0' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub IRC_Helper () {
have_helper ( 'irc' , 'tcp' , 6667 ) || IRC0_Helper ;
}
2012-08-03 19:53:20 +02:00
sub Netbios_ns_Helper () {
2012-08-07 00:54:45 +02:00
have_helper ( 'netbios-ns' , 'udp' , 137 ) ;
2012-08-03 19:53:20 +02:00
}
sub PPTP_Helper () {
2012-08-07 00:54:45 +02:00
have_helper ( 'pptp' , 'tcp' , 1729 ) ;
2012-08-03 19:53:20 +02:00
}
2012-08-07 00:54:45 +02:00
sub SANE0_Helper () {
have_helper ( 'sane-0' , 'tcp' , 6566 ) and $ helpers_aliases { sane } = 'sane-0' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub SANE_Helper () {
2013-04-18 19:30:56 +02:00
have_helper ( 'sane' , 'tcp' , 6566 ) || have_capability 'SANE0_HELPER' ;
2012-08-07 00:54:45 +02:00
}
sub SIP0_Helper () {
have_helper ( 'sip-0' , 'udp' , 5060 ) and $ helpers_aliases { sip } = 'sip-0' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub SIP_Helper () {
2013-04-18 19:30:56 +02:00
have_helper ( 'sip' , 'udp' , 5060 ) || have_capability 'SIP0_HELPER' ;
2012-08-03 19:53:20 +02:00
}
2012-09-22 18:27:13 +02:00
sub SNMP_Helper () {
have_helper ( 'snmp' , 'udp' , 161 ) ;
2012-08-07 00:54:45 +02:00
}
sub TFTP0_Helper () {
have_helper ( 'tftp-0' , 'udp' , 69 ) and $ helpers_aliases { tftp } = 'tftp-0' ;
2010-01-25 19:50:49 +01:00
}
2012-09-22 18:27:13 +02:00
sub TFTP_Helper () {
2013-04-18 19:30:56 +02:00
have_helper ( 'tftp' , 'udp' , 69 ) || have_capability 'TFTP0_HELPER' ;
2012-09-22 18:27:13 +02:00
}
2010-01-25 19:50:49 +01:00
sub Connlimit_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m connlimit --connlimit-above 8" ) ;
2010-01-25 19:50:49 +01:00
}
sub Time_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m time --timestart 11:00" ) ;
2010-01-25 19:50:49 +01:00
}
sub Goto_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -g $sillyname1" ) ;
2010-01-25 19:50:49 +01:00
}
sub Log_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j LOG" ) ;
2010-01-25 19:50:49 +01:00
}
2011-11-12 23:10:48 +01:00
sub Ulog_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j ULOG" ) ;
2011-11-12 23:10:48 +01:00
}
sub NFLog_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j NFLOG" ) ;
2011-11-12 23:10:48 +01:00
}
2010-01-25 19:50:49 +01:00
sub Logmark_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j LOGMARK" ) ;
2010-01-25 16:56:16 +01:00
}
2010-02-10 23:50:26 +01:00
sub Flow_Filter () {
2011-11-01 14:21:34 +01:00
$ tc && system ( "$tc filter add flow help 2>&1 | grep -q ^Usage" ) == 0 ;
2010-02-10 23:50:26 +01:00
}
2011-11-01 14:34:57 +01:00
sub Basic_Filter () {
$ tc && system ( "$tc filter add basic help 2>&1 | grep -q ^Usage" ) == 0 ;
}
2014-01-03 18:35:34 +01:00
sub Basic_Ematch () {
2014-01-03 21:01:56 +01:00
$ tc && have_capability ( 'BASIC_FILTER' ) && system ( "$tc filter add basic help 2>&1 | egrep -q match" ) == 0 ;
2014-01-03 18:35:34 +01:00
}
2010-07-04 18:08:04 +02:00
sub Fwmark_Rt_Mask () {
2010-07-05 17:51:13 +02:00
$ ip && system ( "$ip rule add help 2>&1 | grep -q /MASK" ) == 0 ;
2010-07-04 18:08:04 +02:00
}
2010-08-27 17:35:33 +02:00
sub Mark_Anywhere () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j MARK --set-mark 5" ) ;
2010-08-27 17:35:33 +02:00
}
2010-11-24 19:46:06 +01:00
sub Header_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m ipv6header --header 255 -j ACCEPT" ) ;
2010-11-24 19:46:06 +01:00
}
2011-01-29 23:18:53 +01:00
sub Account_Target () {
if ( $ family == F_IPV4 ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j ACCOUNT --addr 192.168.1.0/29 --tname $sillyname" ) ;
2011-01-29 23:18:53 +01:00
} else {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j ACCOUNT --addr 1::/122 --tname $sillyname" ) ;
2011-01-29 23:18:53 +01:00
}
}
2011-09-22 00:20:50 +02:00
sub Condition_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m condition --condition foo" ) ;
2011-09-22 00:20:50 +02:00
}
2011-05-19 02:08:07 +02:00
sub Audit_Target () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -j AUDIT --type drop" ) ;
2011-05-19 02:08:07 +02:00
}
2011-10-01 22:54:52 +02:00
sub Iptables_S () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -S INPUT" )
2011-10-01 22:54:52 +02:00
}
2011-12-04 23:35:53 +01:00
sub Ct_Target () {
my $ ct_target ;
if ( have_capability 'RAW_TABLE' ) {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -t raw -N $sillyname" ) ;
$ ct_target = qt1 ( "$iptables $iptablesw -t raw -A $sillyname -j CT --notrack" ) ;
2011-12-04 23:35:53 +01:00
}
$ ct_target ;
}
2012-01-06 01:49:26 +01:00
sub Statistic_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m statistic --mode nth --every 2 --packet 1" ) ;
2012-01-05 00:46:01 +01:00
}
2012-08-03 00:38:23 +02:00
2012-02-02 21:54:00 +01:00
sub Imq_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j IMQ --todev 0" ) ;
2012-02-20 17:47:48 +01:00
}
sub Dscp_Match () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -m dscp --dscp 0" ) ;
2012-02-20 17:47:48 +01:00
}
sub Dscp_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j DSCP --set-dscp 0" ) ;
2012-02-02 21:54:00 +01:00
}
2012-07-15 16:54:46 +02:00
sub RPFilter_Match () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -m rpfilter" ) ;
2012-07-15 16:54:46 +02:00
}
2012-07-28 17:19:05 +02:00
sub NFAcct_Match () {
my $ result ;
if ( qt1 ( "nfacct add $sillyname" ) ) {
2013-09-04 19:16:36 +02:00
$ result = qt1 ( "$iptables $iptablesw -A $sillyname -m nfacct --nfacct-name $sillyname" ) ;
2012-07-28 20:21:16 +02:00
qt ( "$iptables -D $sillyname -m nfacct --nfacct-name $sillyname" ) ;
2012-07-28 17:19:05 +02:00
qt ( "nfacct del $sillyname" ) ;
}
$ result ;
}
2012-05-15 02:12:46 +02:00
sub GeoIP_Match () {
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m geoip --src-cc US" ) ;
2012-05-15 02:12:46 +02:00
}
2012-10-23 00:42:13 +02:00
sub Checksum_Target () {
2013-09-04 19:16:36 +02:00
have_capability ( 'MANGLE_ENABLED' ) && qt1 ( "$iptables $iptablesw -t mangle -A $sillyname -j CHECKSUM --checksum-fill" ) ;
2012-10-23 00:42:13 +02:00
}
2013-01-04 18:17:57 +01:00
sub Arptables_JF () {
my $ arptables = $ config { ARPTABLES } ;
$ arptables = which ( 'arptables' ) unless supplied $ arptables ;
if ( $ arptables && - f $ arptables && - x _ ) {
$ config { ARPTABLES } = $ arptables ;
qt ( "$arptables -L OUT" ) ;
}
}
2015-01-02 18:05:06 +01:00
sub Iface_Match () {
qt1 ( "$iptables $iptablesw -A $sillyname -m iface --iface lo --loopback" ) ;
}
2015-04-01 00:53:05 +02:00
sub Tcpmss_Target () {
qt1 ( "$iptables $iptablesw -A $sillyname -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu" ) ;
}
2015-01-02 18:05:06 +01:00
2010-01-29 01:39:45 +01:00
our % detect_capability =
2011-01-29 23:18:53 +01:00
( ACCOUNT_TARGET = > \ & Account_Target ,
2012-08-03 00:38:23 +02:00
AMANDA_HELPER = > \ & Amanda_Helper ,
2013-01-04 18:17:57 +01:00
ARPTABLESJF = > \ & Arptables_JF ,
2011-05-19 02:08:07 +02:00
AUDIT_TARGET = > \ & Audit_Target ,
2011-01-29 23:18:53 +01:00
ADDRTYPE = > \ & Addrtype ,
2011-11-01 14:34:57 +01:00
BASIC_FILTER = > \ & Basic_Filter ,
2014-01-03 18:35:34 +01:00
BASIC_EMATCH = > \ & Basic_Ematch ,
2012-10-23 00:42:13 +02:00
CHECKSUM_TARGET = > \ & Checksum_Target ,
2010-01-29 22:09:53 +01:00
CLASSIFY_TARGET = > \ & Classify_Target ,
2011-09-22 00:20:50 +02:00
CONDITION_MATCH = > \ & Condition_Match ,
2010-01-29 22:09:53 +01:00
COMMENTS = > \ & Comments ,
CONNLIMIT_MATCH = > \ & Connlimit_Match ,
2010-01-29 01:39:45 +01:00
CONNMARK = > \ & Connmark ,
CONNMARK_MATCH = > \ & Connmark_Match ,
2010-01-29 22:09:53 +01:00
CONNTRACK_MATCH = > \ & Conntrack_Match ,
2011-12-17 17:59:27 +01:00
CT_TARGET = > \ & Ct_Target ,
2012-02-20 17:47:48 +01:00
DSCP_MATCH = > \ & Dscp_Match ,
DSCP_TARGET = > \ & Dscp_Target ,
2010-01-29 01:39:45 +01:00
ENHANCED_REJECT = > \ & Enhanced_Reject ,
2013-03-10 17:04:47 +01:00
EMULTIPORT = > \ & Emultiport ,
2010-01-29 01:39:45 +01:00
EXMARK = > \ & Exmark ,
2010-02-10 23:50:26 +01:00
FLOW_FILTER = > \ & Flow_Filter ,
2012-08-03 00:38:23 +02:00
FTP_HELPER = > \ & FTP_Helper ,
2012-08-07 00:54:45 +02:00
FTP0_HELPER = > \ & FTP0_Helper ,
2010-07-04 18:08:04 +02:00
FWMARK_RT_MASK = > \ & Fwmark_Rt_Mask ,
2012-05-15 02:12:46 +02:00
GEOIP_MATCH = > \ & GeoIP_Match ,
2010-01-29 22:09:53 +01:00
GOTO_TARGET = > \ & Goto_Target ,
2012-08-03 19:53:20 +02:00
H323_HELPER = > \ & H323_Helpers ,
2010-01-29 01:39:45 +01:00
HASHLIMIT_MATCH = > \ & Hashlimit_Match ,
2010-11-24 19:46:06 +01:00
HEADER_MATCH = > \ & Header_Match ,
2012-08-05 17:08:20 +02:00
HELPER_MATCH = > \ & Helper_Match ,
2015-01-02 18:05:06 +01:00
IFACE_MATCH = > \ & Iface_Match ,
2012-02-02 21:54:00 +01:00
IMQ_TARGET = > \ & Imq_Target ,
2010-01-29 01:39:45 +01:00
IPMARK_TARGET = > \ & IPMark_Target ,
2010-01-29 22:09:53 +01:00
IPP2P_MATCH = > \ & Ipp2p_Match ,
IPRANGE_MATCH = > \ & IPRange_Match ,
IPSET_MATCH = > \ & IPSet_Match ,
2014-01-02 18:36:35 +01:00
IPSET_MATCH_NOMATCH = > \ & IPSet_Match_Nomatch ,
IPSET_MATCH_COUNTERS = > \ & IPSet_Match_Counters ,
2012-08-03 00:38:23 +02:00
IRC_HELPER = > \ & IRC_Helper ,
2012-08-07 00:54:45 +02:00
IRC0_HELPER = > \ & IRC0_Helper ,
2010-08-04 06:06:17 +02:00
OLD_IPSET_MATCH = > \ & Old_IPSet_Match ,
2011-06-23 15:36:35 +02:00
IPSET_V5 = > \ & IPSET_V5 ,
2011-10-01 22:54:52 +02:00
IPTABLES_S = > \ & Iptables_S ,
2010-01-29 22:09:53 +01:00
KLUDGEFREE = > \ & Kludgefree ,
LENGTH_MATCH = > \ & Length_Match ,
LOGMARK_TARGET = > \ & Logmark_Target ,
2010-01-29 01:39:45 +01:00
LOG_TARGET = > \ & Log_Target ,
2011-11-12 23:10:48 +01:00
ULOG_TARGET = > \ & Ulog_Target ,
NFLOG_TARGET = > \ & NFLog_Target ,
2010-01-29 22:09:53 +01:00
MANGLE_ENABLED = > \ & Mangle_Enabled ,
MANGLE_FORWARD = > \ & Mangle_Forward ,
MARK = > \ & Mark ,
2010-08-27 17:35:33 +02:00
MARK_ANYWHERE = > \ & Mark_Anywhere ,
2013-02-27 18:25:26 +01:00
MASQUERADE_TGT = > \ & Masquerade_Tgt ,
2010-01-29 22:09:53 +01:00
MULTIPORT = > \ & Multiport ,
NAT_ENABLED = > \ & Nat_Enabled ,
2012-08-03 00:38:23 +02:00
NETBIOS_NS_HELPER = > \ & Netbios_ns_Helper ,
2010-01-29 22:09:53 +01:00
NEW_CONNTRACK_MATCH = > \ & New_Conntrack_Match ,
2012-07-28 17:19:05 +02:00
NFACCT_MATCH = > \ & NFAcct_Match ,
2010-01-29 22:09:53 +01:00
NFQUEUE_TARGET = > \ & Nfqueue_Target ,
OLD_CONNTRACK_MATCH = > \ & Old_Conntrack_Match ,
2010-01-29 01:39:45 +01:00
OLD_HL_MATCH = > \ & Old_Hashlimit_Match ,
2010-01-29 22:09:53 +01:00
OLD_IPP2P_MATCH = > \ & Old_Ipp2p_Match ,
2013-04-09 23:04:16 +02:00
NEW_TOS_MATCH = > \ & New_Tos_Match ,
2010-01-29 22:09:53 +01:00
OWNER_MATCH = > \ & Owner_Match ,
2012-03-26 05:18:20 +02:00
OWNER_NAME_MATCH = > \ & Owner_Name_Match ,
2010-01-29 22:09:53 +01:00
PERSISTENT_SNAT = > \ & Persistent_Snat ,
PHYSDEV_BRIDGE = > \ & Physdev_Bridge ,
PHYSDEV_MATCH = > \ & Physdev_Match ,
POLICY_MATCH = > \ & Policy_Match ,
2012-08-03 00:38:23 +02:00
PPTP_HELPER = > \ & PPTP_Helper ,
2010-01-29 22:09:53 +01:00
RAW_TABLE = > \ & Raw_Table ,
2011-08-13 20:14:29 +02:00
RAWPOST_TABLE = > \ & Rawpost_Table ,
2010-01-29 22:09:53 +01:00
REALM_MATCH = > \ & Realm_Match ,
2013-10-07 16:54:52 +02:00
REAP_OPTION = > \ & Reap_Option ,
2010-01-29 22:09:53 +01:00
RECENT_MATCH = > \ & Recent_Match ,
2012-07-15 16:54:46 +02:00
RPFILTER_MATCH = > \ & RPFilter_Match ,
2012-08-03 00:38:23 +02:00
SANE_HELPER = > \ & SANE_Helper ,
2012-08-07 00:54:45 +02:00
SANE0_HELPER = > \ & SANE0_Helper ,
2012-08-03 00:38:23 +02:00
SIP_HELPER = > \ & SIP_Helper ,
2012-08-07 00:54:45 +02:00
SIP0_HELPER = > \ & SIP0_Helper ,
2012-08-03 00:38:23 +02:00
SNMP_HELPER = > \ & SNMP_Helper ,
2012-01-06 01:49:26 +01:00
STATISTIC_MATCH = > \ & Statistic_Match ,
2014-12-29 00:23:30 +01:00
TARPIT_TARGET = > \ & Tarpit_Target ,
2010-01-29 22:09:53 +01:00
TCPMSS_MATCH = > \ & Tcpmss_Match ,
2015-04-01 00:53:05 +02:00
TCPMSS_TARGET = > \ & Tcpmss_Target ,
2012-08-03 00:38:23 +02:00
TFTP_HELPER = > \ & TFTP_Helper ,
2012-08-07 00:54:45 +02:00
TFTP0_HELPER = > \ & TFTP0_Helper ,
2010-01-29 22:09:53 +01:00
TIME_MATCH = > \ & Time_Match ,
TPROXY_TARGET = > \ & Tproxy_Target ,
2013-03-10 18:07:52 +01:00
UDPLITEREDIRECT = > \ & Udpliteredirect ,
2010-01-29 22:09:53 +01:00
USEPKTTYPE = > \ & Usepkttype ,
XCONNMARK_MATCH = > \ & Xconnmark_Match ,
XCONNMARK = > \ & Xconnmark ,
XMARK = > \ & Xmark ,
XMULTIPORT = > \ & Xmultiport ,
2010-01-29 01:39:45 +01:00
) ;
sub detect_capability ( $ ) {
my $ capability = shift ;
2010-01-29 19:38:22 +01:00
my $ function = $ detect_capability { $ capability } ;
assert ( ( reftype ( $ function ) || '' ) eq 'CODE' ) ;
$ function - > ( ) ;
}
#
# Report the passed capability
#
2013-02-19 00:15:26 +01:00
sub have_capability ( $;$ ) {
my ( $ capability , $ required ) = @ _ ;
2010-01-29 19:38:22 +01:00
our % detect_capability ;
2011-07-21 21:57:20 +02:00
my $ setting = $ capabilities { $ capability } ;
2010-01-29 19:38:22 +01:00
2011-07-21 21:57:20 +02:00
$ setting = $ capabilities { $ capability } = detect_capability ( $ capability ) unless defined $ setting ;
2013-02-19 00:15:26 +01:00
$ used { $ capability } = $ required ? 2 : 1 if $ setting ;
2013-02-18 17:48:18 +01:00
2011-07-21 21:57:20 +02:00
$ setting ;
2010-01-29 01:39:45 +01:00
}
2010-01-25 16:56:16 +01:00
#
2010-01-25 19:50:49 +01:00
# Determine which optional facilities are supported by iptables/netfilter
2010-01-25 16:56:16 +01:00
#
2010-02-10 23:50:26 +01:00
sub determine_capabilities () {
2010-01-25 19:50:49 +01:00
my $ pid = $$ ;
2010-01-29 19:38:22 +01:00
$ capabilities { CAPVERSION } = $ globals { CAPVERSION } ;
determine_kernelversion ;
2010-01-25 19:50:49 +01:00
$ sillyname = "fooX$pid" ;
$ sillyname1 = "foo1X$pid" ;
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -N $sillyname" ) ;
qt1 ( "$iptables $iptablesw -N $sillyname1" ) ;
2010-01-25 19:50:49 +01:00
fatal_error 'Your kernel/iptables do not include state match support. No version of Shorewall will run on this system'
2010-06-07 16:30:56 +02:00
unless
2013-09-04 19:16:36 +02:00
qt1 ( "$iptables $iptablesw -A $sillyname -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT" ) ||
qt1 ( "$iptables $iptablesw -A $sillyname -m state --state ESTABLISHED,RELATED -j ACCEPT" ) ; ;
2010-06-07 16:30:56 +02:00
2011-07-21 21:57:20 +02:00
$ globals { KLUDGEFREE } = $ capabilities { KLUDGEFREE } = detect_capability 'KLUDGEFREE' ;
2010-06-07 16:30:56 +02:00
2010-01-25 19:50:49 +01:00
unless ( $ config { LOAD_HELPERS_ONLY } ) {
2010-01-29 19:38:22 +01:00
#
# Using 'detect_capability()' is a bit less efficient than calling the individual detection
# functions but it ensures that %detect_capability is initialized properly.
#
$ capabilities { NAT_ENABLED } = detect_capability ( 'NAT_ENABLED' ) ;
$ capabilities { PERSISTENT_SNAT } = detect_capability ( 'PERSISTENT_SNAT' ) ;
$ capabilities { MANGLE_ENABLED } = detect_capability ( 'MANGLE_ENABLED' ) ;
2010-06-07 16:30:56 +02:00
2010-01-29 19:38:22 +01:00
if ( $ capabilities { CONNTRACK_MATCH } = detect_capability ( 'CONNTRACK_MATCH' ) ) {
$ capabilities { NEW_CONNTRACK_MATCH } = detect_capability ( 'NEW_CONNTRACK_MATCH' ) ;
$ capabilities { OLD_CONNTRACK_MATCH } = detect_capability ( 'OLD_CONNTRACK_MATCH' ) ;
2010-01-25 19:50:49 +01:00
} else {
$ capabilities { NEW_CONNTRACK_MATCH } = '' ;
$ capabilities { OLD_CONNTRACK_MATCH } = '' ;
}
2011-07-21 21:57:20 +02:00
$ capabilities { MULTIPORT } = detect_capability ( 'MULTIPORT' ) ;
2010-06-07 16:30:56 +02:00
$ capabilities { XMULTIPORT } = detect_capability ( 'XMULTIPORT' ) ;
2013-03-10 17:04:47 +01:00
$ capabilities { EMULTIPORT } = detect_capability ( 'EMULTIPORT' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { POLICY_MATCH } = detect_capability ( 'POLICY_MATCH' ) ;
2010-01-25 19:50:49 +01:00
2010-01-29 19:38:22 +01:00
if ( $ capabilities { PHYSDEV_MATCH } = detect_capability ( 'PHYSDEV_MATCH' ) ) {
$ capabilities { PHYSDEV_BRIDGE } = detect_capability ( 'PHYSDEV_BRIDGE' ) ;
2010-01-25 19:50:49 +01:00
} else {
$ capabilities { PHYSDEV_BRIDGE } = '' ;
}
2011-07-21 21:57:20 +02:00
$ capabilities { IPRANGE_MATCH } = detect_capability ( 'IPRANGE_MATCH' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { RECENT_MATCH } = detect_capability ( 'RECENT_MATCH' ) ;
2013-10-07 16:54:52 +02:00
$ capabilities { REAP_OPTION } = detect_capability ( 'REAP_OPTION' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { OWNER_MATCH } = detect_capability ( 'OWNER_MATCH' ) ;
2012-03-26 05:18:20 +02:00
$ capabilities { OWNER_NAME_MATCH }
= detect_capability ( 'OWNER_NAME_MATCH' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { CONNMARK_MATCH } = detect_capability ( 'CONNMARK_MATCH' ) ;
$ capabilities { XCONNMARK_MATCH } = detect_capability ( 'XCONNMARK_MATCH' ) ;
$ capabilities { IPP2P_MATCH } = detect_capability ( 'IPP2P_MATCH' ) ;
$ capabilities { OLD_IPP2P_MATCH } = detect_capability ( 'OLD_IPP2P_MATCH' ) ;
$ capabilities { LENGTH_MATCH } = detect_capability ( 'LENGTH_MATCH' ) ;
$ capabilities { ENHANCED_REJECT } = detect_capability ( 'ENHANCED_REJECT' ) ;
$ capabilities { COMMENTS } = detect_capability ( 'COMMENTS' ) ;
$ capabilities { OLD_HL_MATCH } = detect_capability ( 'OLD_HL_MATCH' ) ;
$ capabilities { HASHLIMIT_MATCH } = detect_capability ( 'HASHLIMIT_MATCH' ) ;
$ capabilities { MARK } = detect_capability ( 'MARK' ) ;
$ capabilities { XMARK } = detect_capability ( 'XMARK' ) ;
$ capabilities { EXMARK } = detect_capability ( 'EXMARK' ) ;
$ capabilities { CONNMARK } = detect_capability ( 'CONNMARK' ) ;
$ capabilities { XCONNMARK } = detect_capability ( 'XCONNMARK' ) ;
$ capabilities { CLASSIFY_TARGET } = detect_capability ( 'CLASSIFY_TARGET' ) ;
$ capabilities { IPMARK_TARGET } = detect_capability ( 'IPMARK_TARGET' ) ;
$ capabilities { TPROXY_TARGET } = detect_capability ( 'TPROXY_TARGET' ) ;
$ capabilities { MANGLE_FORWARD } = detect_capability ( 'MANGLE_FORWARD' ) ;
$ capabilities { RAW_TABLE } = detect_capability ( 'RAW_TABLE' ) ;
2011-08-13 20:14:29 +02:00
$ capabilities { RAWPOST_TABLE } = detect_capability ( 'RAWPOST_TABLE' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { IPSET_MATCH } = detect_capability ( 'IPSET_MATCH' ) ;
$ capabilities { USEPKTTYPE } = detect_capability ( 'USEPKTTYPE' ) ;
$ capabilities { ADDRTYPE } = detect_capability ( 'ADDRTYPE' ) ;
$ capabilities { TCPMSS_MATCH } = detect_capability ( 'TCPMSS_MATCH' ) ;
$ capabilities { NFQUEUE_TARGET } = detect_capability ( 'NFQUEUE_TARGET' ) ;
$ capabilities { REALM_MATCH } = detect_capability ( 'REALM_MATCH' ) ;
$ capabilities { CONNLIMIT_MATCH } = detect_capability ( 'CONNLIMIT_MATCH' ) ;
$ capabilities { TIME_MATCH } = detect_capability ( 'TIME_MATCH' ) ;
$ capabilities { GOTO_TARGET } = detect_capability ( 'GOTO_TARGET' ) ;
$ capabilities { LOG_TARGET } = detect_capability ( 'LOG_TARGET' ) ;
2011-11-12 23:10:48 +01:00
$ capabilities { ULOG_TARGET } = detect_capability ( 'ULOG_TARGET' ) ;
$ capabilities { NFLOG_TARGET } = detect_capability ( 'NFLOG_TARGET' ) ;
2010-01-29 19:38:22 +01:00
$ capabilities { LOGMARK_TARGET } = detect_capability ( 'LOGMARK_TARGET' ) ;
2010-02-14 19:34:19 +01:00
$ capabilities { FLOW_FILTER } = detect_capability ( 'FLOW_FILTER' ) ;
2010-08-27 17:35:33 +02:00
$ capabilities { FWMARK_RT_MASK } = detect_capability ( 'FWMARK_RT_MASK' ) ;
$ capabilities { MARK_ANYWHERE } = detect_capability ( 'MARK_ANYWHERE' ) ;
2011-01-29 23:18:53 +01:00
$ capabilities { ACCOUNT_TARGET } = detect_capability ( 'ACCOUNT_TARGET' ) ;
2014-07-20 16:19:02 +02:00
$ capabilities { HEADER_MATCH } = detect_capability ( 'HEADER_MATCH' ) ;
2011-05-20 16:47:35 +02:00
$ capabilities { AUDIT_TARGET } = detect_capability ( 'AUDIT_TARGET' ) ;
2011-06-23 15:36:35 +02:00
$ capabilities { IPSET_V5 } = detect_capability ( 'IPSET_V5' ) ;
2011-09-22 00:20:50 +02:00
$ capabilities { CONDITION_MATCH } = detect_capability ( 'CONDITION_MATCH' ) ;
2011-10-01 22:54:52 +02:00
$ capabilities { IPTABLES_S } = detect_capability ( 'IPTABLES_S' ) ;
2011-11-01 14:34:57 +01:00
$ capabilities { BASIC_FILTER } = detect_capability ( 'BASIC_FILTER' ) ;
2014-01-03 18:35:34 +01:00
$ capabilities { BASIC_EMATCH } = detect_capability ( 'BASIC_EMATCH' ) ;
2011-12-23 20:59:51 +01:00
$ capabilities { CT_TARGET } = detect_capability ( 'CT_TARGET' ) ;
2012-01-06 01:49:26 +01:00
$ capabilities { STATISTIC_MATCH } = detect_capability ( 'STATISTIC_MATCH' ) ;
2012-02-02 21:54:00 +01:00
$ capabilities { IMQ_TARGET } = detect_capability ( 'IMQ_TARGET' ) ;
2012-02-20 17:47:48 +01:00
$ capabilities { DSCP_MATCH } = detect_capability ( 'DSCP_MATCH' ) ;
$ capabilities { DSCP_TARGET } = detect_capability ( 'DSCP_TARGET' ) ;
2012-05-15 02:12:46 +02:00
$ capabilities { GEOIP_MATCH } = detect_capability ( 'GEOIP_MATCH' ) ;
2012-07-15 16:54:46 +02:00
$ capabilities { RPFILTER_MATCH } = detect_capability ( 'RPFILTER_MATCH' ) ;
2012-07-28 17:19:05 +02:00
$ capabilities { NFACCT_MATCH } = detect_capability ( 'NFACCT_MATCH' ) ;
2012-10-23 00:42:13 +02:00
$ capabilities { CHECKSUM_TARGET } = detect_capability ( 'CHECKSUM_TARGET' ) ;
2014-07-20 16:19:02 +02:00
$ capabilities { ARPTABLESJF } = detect_capability ( 'ARPTABLESJF' ) ;
2013-03-10 18:07:52 +01:00
$ capabilities { MASQUERADE_TGT } = detect_capability ( 'MASQUERADE_TGT' ) ;
$ capabilities { UDPLITEREDIRECT } = detect_capability ( 'UDPLITEREDIRECT' ) ;
2013-04-09 23:04:16 +02:00
$ capabilities { NEW_TOS_MATCH } = detect_capability ( 'NEW_TOS_MATCH' ) ;
2014-12-30 19:22:33 +01:00
$ capabilities { TARPIT_TARGET } = detect_capability ( 'TARPIT_TARGET' ) ;
2015-01-02 18:05:06 +01:00
$ capabilities { IFACE_MATCH } = detect_capability ( 'IFACE_MATCH' ) ;
2015-04-01 00:53:05 +02:00
$ capabilities { TCPMSS_TARGET } = detect_capability ( 'TCPMSS_TARGET' ) ;
2013-06-24 22:07:38 +02:00
2013-04-18 19:30:56 +02:00
unless ( have_capability 'CT_TARGET' ) {
2012-09-22 18:27:13 +02:00
$ capabilities { HELPER_MATCH } = detect_capability 'HELPER_MATCH' ;
}
2010-01-25 19:50:49 +01:00
}
2010-01-25 16:56:16 +01:00
}
2009-02-22 18:30:14 +01:00
#
# Require the passed capability
#
sub require_capability ( $$$ ) {
my ( $ capability , $ description , $ singular ) = @ _ ;
2013-02-19 00:15:26 +01:00
fatal_error "$description require${singular} $capdesc{$capability} in your kernel and iptables" unless have_capability $ capability , 1 ;
2009-02-22 18:30:14 +01:00
}
2012-08-04 04:26:02 +02:00
#
# Return Kernel Version
#
sub kernel_version () {
$ capabilities { KERNELVERSION }
}
2009-02-22 18:30:14 +01:00
#
# Set default config path
#
sub ensure_config_path () {
my $ f = "$globals{SHAREDIR}/configpath" ;
unless ( $ config { CONFIG_PATH } ) {
fatal_error "$f does not exist" unless - f $ f ;
open_file $ f ;
2012-04-14 17:04:28 +02:00
while ( read_a_line ( NORMAL_READ ) ) {
2009-02-22 18:30:14 +01:00
if ( $ currentline =~ /^\s*([a-zA-Z]\w*)=(.*?)\s*$/ ) {
my ( $ var , $ val ) = ( $ 1 , $ 2 ) ;
$ config { $ var } = ( $ val =~ /\"([^\"]*)\"$/ ? $ 1 : $ val ) if exists $ config { $ var } ;
} else {
fatal_error "Unrecognized entry" ;
}
}
fatal_error "CONFIG_PATH not found in $f" unless $ config { CONFIG_PATH } ;
}
@ config_path = split /:/ , $ config { CONFIG_PATH } ;
for ( @ config_path ) {
$ _ . = '/' unless m | / $| ;
}
if ( $ shorewall_dir ) {
$ shorewall_dir = getcwd if $ shorewall_dir =~ m | ^ ( \ . / * ) + $| ;
$ shorewall_dir . = '/' unless $ shorewall_dir =~ m | / $| ;
unshift @ config_path , $ shorewall_dir if $ shorewall_dir ne $ config_path [ 0 ] ;
$ config { CONFIG_PATH } = join ':' , @ config_path ;
}
}
#
# Set $shorewall_dir
#
sub set_shorewall_dir ( $ ) {
$ shorewall_dir = shift ;
2014-12-23 21:27:37 +01:00
fatal_error "$shorewall_dir is not an existing directory" unless - d $ shorewall_dir ;
2009-02-22 18:30:14 +01:00
ensure_config_path ;
}
#
2011-06-23 15:37:21 +02:00
# Update the configuration file
2009-02-22 18:30:14 +01:00
#
2011-06-24 20:47:34 +02:00
sub conditional_quote ( $ ) {
my $ val = shift ;
unless ( $ val =~ /^[-\w\/\.]*$/ ) {
#
# Funny characters (including whitespace) -- use double quotes unless the thing is single-quoted
#
$ val = qq( "$val" ) unless $ val =~ /^'.+'$/ ;
}
$ val ;
}
2011-06-26 06:08:32 +02:00
#
# Update the shorewall[6].conf file. Save the current file with a .bak suffix.
#
2015-08-31 20:21:18 +02:00
sub update_default ($$) {
my ( $ var , $ val ) = @ _ ;
$ config { $ var } = $ val unless defined $ config { $ var } ;
}
2015-08-31 23:21:41 +02:00
sub update_config_file ( $ ) {
my ( $ annotate ) = @ _ ;
2011-06-23 15:37:21 +02:00
2011-11-20 16:03:33 +01:00
sub is_set ( $ ) {
2011-11-27 23:12:51 +01:00
my $ value = $ _ [ 0 ] ;
defined ( $ value ) && lc ( $ value ) eq 'yes' ;
2011-11-20 16:03:33 +01:00
}
my $ wide = is_set $ config { WIDE_TC_MARKS } ;
my $ high = is_set $ config { HIGH_ROUTE_MARKS } ;
#
# Establish default values for the mark layout items
#
2012-05-18 20:37:49 +02:00
$ config { TC_BITS } = ( $ wide ? 14 : 8 ) unless defined $ config { TC_BITS } ;
$ config { MASK_BITS } = ( $ wide ? 16 : 8 ) unless defined $ config { MASK_BITS } ;
$ config { PROVIDER_OFFSET } = ( $ high ? $ wide ? 16 : 8 : 0 ) unless defined $ config { PROVIDER_OFFSET } ;
$ config { PROVIDER_BITS } = 8 unless defined $ config { PROVIDER_BITS } ;
2011-11-20 16:03:33 +01:00
2015-08-25 23:36:14 +02:00
unless ( supplied $ config { LOGLIMIT } ) {
if ( $ config { LOGRATE } || $ config { LOGBURST } ) {
my $ limit ;
2015-08-26 21:50:56 +02:00
2015-08-25 23:36:14 +02:00
if ( supplied $ config { LOGRATE } ) {
fatal_error "Invalid LOGRATE ($config{LOGRATE})" unless $ config { LOGRATE } =~ /^\d+\/(second|minute)$/ ;
$ limit = $ config { LOGRATE } ;
}
if ( supplied $ config { LOGBURST } ) {
fatal_error "Invalid LOGBURST ($config{LOGBURST})" unless $ config { LOGBURST } =~ /^\d+$/ ;
$ limit . = ":$config{LOGBURST}" ;
}
$ config { LOGLIMIT } = $ limit ;
}
}
2015-08-26 00:55:49 +02:00
unless ( supplied $ config { BLACKLIST } ) {
if ( $ config { BLACKLISTNEWONLY } ) {
default_yes_no 'BLACKLISTNEWONLY' , '' ;
if ( have_capability 'RAW_TABLE' ) {
$ globals { BLACKLIST_STATES } = $ config { BLACKLISTNEWONLY } ? 'NEW,INVALID,UNTRACKED' : 'NEW,ESTABLISHED,INVALID,UNTRACKED' ;
} else {
$ globals { BLACKLIST_STATES } = $ config { BLACKLISTNEWONLY } ? 'NEW,INVALID' : 'NEW,ESTABLISHED,INVALID' ;
}
$ config { BLACKLIST } = $ globals { BLACKLIST_STATES } ;
}
}
2015-08-31 20:21:18 +02:00
update_default ( 'USE_DEFAULT_RT' , 'No' ) ;
update_default ( 'EXPORTMODULES' , 'No' ) ;
2015-10-12 20:45:58 +02:00
update_default ( 'RESTART' , 'reload' ) ;
2015-08-28 00:15:03 +02:00
2011-06-24 22:40:32 +02:00
my $ fn ;
2011-06-25 00:01:25 +02:00
unless ( - d "$globals{SHAREDIR}/configfiles/" ) {
2011-06-24 22:40:32 +02:00
#
# Debian or derivative
#
2012-05-07 02:30:17 +02:00
$ fn = $ annotate ? "$shorewallrc{SHAREDIR}/doc/${product}/default-config/${product}.conf.annotated" : "$shorewallrc{SHAREDIR}/doc/${product}/default-config/${product}.conf" ;
2011-06-24 22:40:32 +02:00
} else {
#
# The rest of the World
#
$ fn = $ annotate ? "$globals{SHAREDIR}/configfiles/${product}.conf.annotated" : "$globals{SHAREDIR}/configfiles/${product}.conf" ;
}
2015-08-01 20:11:35 +02:00
if ( - f $ fn ) {
2011-06-23 15:37:21 +02:00
my ( $ template , $ output ) ;
open $ template , '<' , $ fn or fatal_error "Unable to open $fn: $!" ;
2012-04-24 23:52:57 +02:00
unless ( open $ output , '>' , "$configfile.updated" ) {
2011-06-23 15:37:21 +02:00
close $ template ;
fatal_error "Unable to open $configfile.updated for output: $!" ;
}
while ( <$template> ) {
if ( /^(\w+)="?(.*?)"?$/ ) {
#
# Option assignment -- get value and default
#
2011-06-26 06:08:32 +02:00
my ( $ var , $ val , $ default ) = ( $ 1 , $ config { $ 1 } , $ 2 ) ;
2011-06-23 15:37:21 +02:00
unless ( supplied $ val ) {
#
# Value is either undefined (option not in config file) or is ''
#
if ( defined $ val ) {
#
# OPTION='' - use default if 'Yes' or 'No'
#
2011-06-24 16:22:41 +02:00
$ config { $ var } = $ val = $ default if $ default eq 'Yes' || $ default eq 'No' ;
2011-06-23 15:37:21 +02:00
} else {
#
# Wasn't mentioned in old file - use default value
#
2011-06-24 16:22:41 +02:00
$ config { $ var } = $ val = $ default ;
2011-06-23 15:37:21 +02:00
}
2011-06-24 16:22:41 +02:00
2011-06-23 15:37:21 +02:00
}
2011-06-24 20:47:34 +02:00
$ val = conditional_quote $ val ;
2011-06-23 15:37:21 +02:00
$ _ = "$var=$val\n" ;
}
print $ output "$_" ;
}
close $ template ;
my $ heading_printed ;
2012-02-29 21:34:06 +01:00
for ( grep ! $ converted { $ _ } , keys % deprecated ) {
2011-06-26 06:08:32 +02:00
if ( supplied ( my $ val = $ config { $ _ } ) ) {
2011-06-24 20:47:34 +02:00
if ( lc $ val ne $ deprecated { $ _ } ) {
2011-06-23 15:37:21 +02:00
unless ( $ heading_printed ) {
print $ output << 'EOF' ;
#################################################################################
2011-06-24 16:58:46 +02:00
# D E P R E C A T E D
2011-06-23 15:37:21 +02:00
# O P T I O N S
#################################################################################
EOF
$ heading_printed = 1 ;
}
2011-06-24 20:47:34 +02:00
$ val = conditional_quote $ val ;
print $ output "$_=$val\n\n" ;
2011-06-22 21:31:58 +02:00
2011-06-23 15:37:21 +02:00
warning_message "Deprecated option $_ is being set in your $product.conf file" ;
}
}
}
close $ output ;
fatal_error "Can't rename $configfile to $configfile.bak: $!" unless rename $ configfile , "$configfile.bak" ;
fatal_error "Can't rename $configfile.updated to $configfile: $!" unless rename "$configfile.updated" , $ configfile ;
2012-04-24 23:52:57 +02:00
2011-08-12 05:19:30 +02:00
if ( system ( "diff -q $configfile $configfile.bak > /dev/null" ) ) {
progress_message3 "Configuration file $configfile updated - old file renamed $configfile.bak" ;
} else {
2013-01-03 00:03:07 +01:00
if ( rename "$configfile.bak" , $ configfile ) {
2011-08-12 05:19:30 +02:00
progress_message3 "No update required to configuration file $configfile; $configfile.bak not saved" ;
} else {
2013-01-03 00:03:07 +01:00
warning_message "Unable to rename $configfile.bak to $configfile" ;
2012-02-29 21:34:06 +01:00
progress_message3 "No update required to configuration file $configfile" ;
2011-08-12 05:19:30 +02:00
}
}
2011-06-23 15:37:21 +02:00
} else {
fatal_error "$fn does not exist" ;
}
}
#
# Small functions called by get_configuration. We separate them so profiling is more useful
#
2015-08-31 23:21:41 +02:00
sub process_shorewall_conf ( $$ ) {
my ( $ update , $ annotate ) = @ _ ;
2011-06-22 19:56:25 +02:00
my $ file = find_file "$product.conf" ;
2009-02-22 18:30:14 +01:00
if ( - f $ file ) {
2011-06-18 22:03:55 +02:00
$ globals { CONFIGDIR } = $ configfile = $ file ;
2010-08-13 02:54:07 +02:00
$ globals { CONFIGDIR } =~ s/$product.conf// ;
2009-02-22 18:30:14 +01:00
if ( - r _ ) {
open_file $ file ;
2010-03-28 22:09:04 +02:00
first_entry "Processing $file..." ;
2011-06-19 01:55:00 +02:00
#
2011-06-26 16:45:09 +02:00
# Don't expand shell variables or allow embedded scripting
2011-06-19 01:55:00 +02:00
#
2012-04-11 02:01:38 +02:00
while ( read_a_line ( STRIP_COMMENTS | SUPPRESS_WHITESPACE | CHECK_GUNK ) ) {
2009-02-22 18:30:14 +01:00
if ( $ currentline =~ /^\s*([a-zA-Z]\w*)=(.*?)\s*$/ ) {
my ( $ var , $ val ) = ( $ 1 , $ 2 ) ;
2011-06-26 15:50:22 +02:00
2015-08-21 21:42:19 +02:00
if ( exists $ config { $ var } ) {
if ( $ eliminated { $ var } && ! $ update ) {
fatal_error "The $var configuration option has been superceded - please run '$product update'" ;
}
} elsif ( exists $ renamed { $ var } ) {
$ var = $ renamed { $ var } ;
} else {
if ( $ eliminated { $ var } ) {
2015-08-01 20:11:35 +02:00
warning_message "The $var configuration option is no longer supported" ;
2012-08-02 20:06:41 +02:00
} else {
warning_message "Unknown configuration option ($var) ignored" ;
}
2015-08-21 21:42:19 +02:00
next ;
2012-08-02 20:06:41 +02:00
}
2009-02-22 18:30:14 +01:00
2011-06-26 06:08:32 +02:00
$ config { $ var } = ( $ val =~ /\"([^\"]*)\"$/ ? $ 1 : $ val ) ;
2012-04-24 23:52:57 +02:00
2012-01-08 04:58:45 +01:00
warning_message "Option $var=$val is deprecated"
if $ deprecated { $ var } && supplied $ val && lc $ config { $ var } ne $ deprecated { $ var } ;
2009-02-22 18:30:14 +01:00
} else {
2011-06-26 15:50:22 +02:00
fatal_error "Unrecognized $product.conf entry" ;
2009-02-22 18:30:14 +01:00
}
}
} else {
fatal_error "Cannot read $file (Hint: Are you root?)" ;
}
} else {
fatal_error "$file does not exist!" ;
}
2011-06-19 01:33:41 +02:00
2011-06-22 21:31:58 +02:00
#
# Now update the config file if asked
#
2015-08-31 23:21:41 +02:00
update_config_file ( $ annotate ) if $ update ;
2011-06-26 16:45:09 +02:00
#
# Config file update requires that the option values not have
# Shell variables expanded. We do that now.
#
for ( values % config ) {
if ( supplied $ _ ) {
2012-04-01 22:19:38 +02:00
expand_variables ( $ _ ) unless /^'(.+)'$/ ;
2011-06-26 16:45:09 +02:00
}
2011-06-26 06:08:32 +02:00
}
2009-02-22 18:30:14 +01:00
}
#
# Process the records in the capabilities file
#
sub read_capabilities () {
2012-04-11 02:01:38 +02:00
while ( read_a_line ( STRIP_COMMENTS | SUPPRESS_WHITESPACE | CHECK_GUNK ) ) {
2009-02-22 18:30:14 +01:00
if ( $ currentline =~ /^([a-zA-Z]\w*)=(.*)$/ ) {
my ( $ var , $ val ) = ( $ 1 , $ 2 ) ;
unless ( exists $ capabilities { $ var } ) {
warning_message "Unknown capability ($var) ignored" ;
next ;
}
2012-08-03 00:38:23 +02:00
$ val = $ val =~ /^\"([^\"]*)\"$/ ? $ 1 : $ val ;
2012-08-03 01:44:02 +02:00
$ capabilities { $ var } = $ var =~ /VERSION$/ ? $ val : $ val ne '' ;
2009-02-22 18:30:14 +01:00
} else {
fatal_error "Unrecognized capabilities entry" ;
}
}
2009-12-19 21:42:39 +01:00
unless ( $ capabilities { KERNELVERSION } ) {
2009-12-19 22:47:12 +01:00
warning_message "Your capabilities file does not contain a Kernel Version -- using 2.6.30" ;
$ capabilities { KERNELVERSION } = 20630 ;
2009-12-19 21:42:39 +01:00
}
2015-04-04 18:34:23 +02:00
#
# Assume that this is available when using an old capabilities files
#
2015-04-04 01:35:50 +02:00
$ capabilities { TCPMSS_TARGET } = 1 if ( ( $ capabilities { CAPVERSION } || 0 ) < 40609 ) ;
2015-04-03 23:46:50 +02:00
2013-04-18 19:30:56 +02:00
$ helpers_aliases { ftp } = 'ftp-0' , $ capabilities { FTP_HELPER } = 1 if $ capabilities { FTP0_HELPER } ;
$ helpers_aliases { irc } = 'irc-0' , $ capabilities { IRC_HELPER } = 1 if $ capabilities { IRC0_HELPER } ;
$ helpers_aliases { sane } = 'sane-0' , $ capabilities { SANE_HELPER } = 1 if $ capabilities { SANE0_HELPER } ;
$ helpers_aliases { sip } = 'sip-0' , $ capabilities { SIP_HELPER } = 1 if $ capabilities { SIP0_HELPER } ;
$ helpers_aliases { tftp } = 'tftp-0' , $ capabilities { TFTP_HELPER } = 1 if $ capabilities { TFTP0_HELPER } ;
2010-01-25 19:50:49 +01:00
for ( keys % capabilities ) {
$ capabilities { $ _ } = '' unless defined $ capabilities { $ _ } ;
}
2010-02-11 16:29:41 +01:00
2011-07-21 21:57:20 +02:00
$ globals { KLUDGEFREE } = $ capabilities { KLUDGEFREE } ;
2012-08-07 00:54:45 +02:00
2009-02-22 18:30:14 +01:00
}
#
2015-08-27 20:26:26 +02:00
# Get the system's capabilities by probing
2009-02-22 18:30:14 +01:00
#
2015-08-27 20:26:26 +02:00
sub get_capabilities ($)
2013-02-18 17:48:18 +01:00
{
2015-08-27 20:26:26 +02:00
$ iptables = $ config { $ toolNAME } ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
if ( $ iptables ) {
fatal_error "$toolNAME=$iptables does not exist or is not executable" unless - x $ iptables ;
} else {
fatal_error "Can't find $toolname executable" unless $ iptables = which $ toolname ;
}
#
# Determine if iptables supports the -w option
#
$ iptablesw = qt1 ( "$iptables -w -L -n" ) ? '-w' : '' ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
my $ iptables_restore = $ iptables . '-restore' ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
fatal_error "$iptables_restore does not exist or is not executable" unless - x $ iptables_restore ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
$ tc = $ config { TC } || which 'tc' ;
2010-02-10 23:50:26 +01:00
2015-08-27 20:26:26 +02:00
if ( $ tc ) {
fatal_error "TC=$tc does not exist or is not executable" unless - x $ tc ;
}
2010-02-10 23:50:26 +01:00
2015-08-27 20:26:26 +02:00
$ ip = $ config { IP } || which 'ip' ;
2010-07-05 17:39:32 +02:00
2015-08-27 20:26:26 +02:00
if ( $ ip ) {
fatal_error "IP=$ip does not exist or is not executable" unless - x $ ip ;
}
2010-07-05 17:39:32 +02:00
2015-08-27 20:26:26 +02:00
load_kernel_modules ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
determine_capabilities unless $ _ [ 0 ] ;
2009-02-22 18:30:14 +01:00
}
#
# Deal with options that we no longer support
#
sub unsupported_yes_no ( $ ) {
my $ option = shift ;
default_yes_no $ option , '' ;
2009-06-13 16:07:55 +02:00
fatal_error "$option=Yes is not supported by Shorewall $globals{VERSION}" if $ config { $ option } ;
2009-02-22 18:30:14 +01:00
}
2009-09-06 18:51:32 +02:00
sub unsupported_yes_no_warning ( $ ) {
my $ option = shift ;
default_yes_no $ option , '' ;
warning_message "$option=Yes is not supported by Shorewall $globals{VERSION}" if $ config { $ option } ;
}
2010-11-07 01:04:17 +01:00
#
# Process the params file
#
2014-10-29 20:22:00 +01:00
sub get_params ( $ ) {
my $ export = $ _ [ 0 ] ;
2010-12-02 19:14:45 +01:00
my $ fn = find_file 'params' ;
2010-11-07 01:04:17 +01:00
2012-03-06 00:42:53 +01:00
my % reserved = ( COMMAND = > 1 , CONFDIR = > 1 , SHAREDIR = > 1 , VARDIR = > 1 ) ;
2010-12-02 19:14:45 +01:00
if ( - f $ fn ) {
2014-10-29 20:22:00 +01:00
my $ shellpath = $ export ? '/bin/sh' : $ config { SHOREWALL_SHELL } || '/bin/sh' ;
$ shellpath = which ( $ shellpath ) unless $ shellpath =~ '/' ;
fatal_error "SHOREWALL_SHELL ($shellpath) is not found or is not executable" unless - x $ shellpath ;
2010-11-07 03:02:14 +01:00
progress_message2 "Processing $fn ..." ;
2010-11-07 01:04:17 +01:00
2014-10-29 20:22:00 +01:00
my $ command = "$shellpath $FindBin::Bin/getparams $fn " . join ( ':' , @ config_path ) . " $family" ;
2010-12-02 00:04:33 +01:00
#
# getparams silently sources the params file under 'set -a', then executes 'export -p'
#
2010-11-13 19:59:09 +01:00
my @ params = `$command` ;
2010-11-07 01:04:17 +01:00
fatal_error "Processing of $fn failed" if $? ;
2010-12-03 22:40:11 +01:00
if ( $ debug ) {
print "Params:\n" ;
print $ _ for @ params ;
}
2012-04-24 23:52:57 +02:00
2010-12-03 17:05:11 +01:00
my ( $ variable , $ bug ) ;
2010-12-01 19:11:02 +01:00
2010-12-01 19:41:49 +01:00
if ( $ params [ 0 ] =~ /^declare/ ) {
2010-12-01 22:57:16 +01:00
#
# getparams was interpreted by bash
#
2010-12-03 01:10:35 +01:00
# - Variable names are preceded by 'declare -x '
# - Param values are delimited by double quotes
# - Embedded double quotes are escaped with '\\'
# - Valueless variables are supported (e.g., 'declare -x foo')
#
2011-09-11 00:46:26 +02:00
$ shell = BASH ;
2010-12-01 19:41:49 +01:00
for ( @ params ) {
2010-12-01 22:18:10 +01:00
if ( /^declare -x (.*?)="(.*[^\\])"$/ ) {
2010-12-01 19:41:49 +01:00
$ params { $ 1 } = $ 2 unless $ 1 eq '_' ;
} elsif ( /^declare -x (.*?)="(.*)$/ ) {
2011-01-20 16:27:14 +01:00
$ params { $ variable = $ 1 } = $ 2 eq '"' ? '' : "${2}\n" ;
2010-12-01 22:57:16 +01:00
} elsif ( /^declare -x (.*)\s+$/ || /^declare -x (.*)=""$/ ) {
2010-12-01 19:41:49 +01:00
$ params { $ 1 } = '' ;
} else {
2011-09-11 00:46:26 +02:00
chomp ;
2010-12-03 17:05:11 +01:00
if ( $ variable ) {
2010-12-03 22:40:11 +01:00
s/"$// ;
$ params { $ variable } . = $ _ ;
} else {
warning_message "Param line ($_) ignored" unless $ bug + + ;
}
2012-04-24 23:52:57 +02:00
}
2010-12-03 22:40:11 +01:00
}
2011-04-03 18:56:30 +02:00
} elsif ( $ params [ 0 ] =~ /^export .*?="/ || $ params [ 0 ] =~ /^export [^\s=]+\s*$/ ) {
2010-12-03 22:40:11 +01:00
#
# getparams interpreted by older (e.g., RHEL 5) Bash
#
# - Variable names preceded by 'export '
# - Variable values are delimited by double quotes
2012-10-14 18:30:27 +02:00
# - Embedded double quotes are escaped with '\'
2011-03-12 22:07:45 +01:00
# - Valueless variables ( e.g., 'export foo') are supported
2010-12-03 22:40:11 +01:00
#
2011-09-11 00:46:26 +02:00
$ shell = OLDBASH ;
2010-12-03 22:40:11 +01:00
for ( @ params ) {
if ( /^export (.*?)="(.*[^\\])"$/ ) {
$ params { $ 1 } = $ 2 unless $ 1 eq '_' ;
} elsif ( /^export (.*?)="(.*)$/ ) {
2011-01-20 16:27:14 +01:00
$ params { $ variable = $ 1 } = $ 2 eq '"' ? '' : "${2}\n" ;
2011-03-13 23:24:48 +01:00
} elsif ( /^export ([^\s=]+)\s*$/ || /^export (.*)=""$/ ) {
2010-12-03 22:40:11 +01:00
$ params { $ 1 } = '' ;
} else {
2011-09-11 00:46:26 +02:00
chomp ;
2010-12-03 22:40:11 +01:00
if ( $ variable ) {
s/"$// ;
2010-12-03 17:05:11 +01:00
$ params { $ variable } . = $ _ ;
} else {
2010-12-03 22:40:11 +01:00
warning_message "Param line ($_) ignored" unless $ bug + + ;
2010-12-03 17:05:11 +01:00
}
2012-04-24 23:52:57 +02:00
}
2010-12-01 19:41:49 +01:00
}
} else {
2010-12-01 22:57:16 +01:00
#
# getparams was interpreted by dash/ash/busybox
#
2010-12-03 01:10:35 +01:00
# - Variable name preceded by 'export '
# - Param values are delimited by single quotes.
# - Embedded single quotes are transformed to the five characters '"'"'
#
2011-09-11 00:46:26 +02:00
$ shell = ASH ;
2010-12-01 19:41:49 +01:00
for ( @ params ) {
2010-12-01 22:57:16 +01:00
if ( /^export (.*?)='(.*'"'"')$/ ) {
2012-04-24 23:52:57 +02:00
$ params { $ variable = $ 1 } = "${2}\n" ;
2010-12-01 22:57:16 +01:00
} elsif ( /^export (.*?)='(.*)'$/ ) {
2010-12-01 19:41:49 +01:00
$ params { $ 1 } = $ 2 unless $ 1 eq '_' ;
} elsif ( /^export (.*?)='(.*)$/ ) {
$ params { $ variable = $ 1 } = "${2}\n" ;
} else {
2011-09-11 00:46:26 +02:00
chomp ;
2010-12-03 17:05:11 +01:00
if ( $ variable ) {
s/'$// ;
$ params { $ variable } . = $ _ ;
} else {
2010-12-03 22:40:11 +01:00
warning_message "Param line ($_) ignored" unless $ bug + + ;
2012-04-24 23:52:57 +02:00
}
2010-12-01 19:41:49 +01:00
}
}
2010-12-01 19:11:02 +01:00
}
2012-03-06 00:42:53 +01:00
for ( keys % params ) {
2012-03-19 17:52:55 +01:00
unless ( $ _ eq 'SHOREWALL_INIT_SCRIPT' ) {
fatal_error "The variable name $_ is reserved and may not be set in the params file"
if /^SW_/ || /^SHOREWALL_/ || ( exists $ config { $ _ } && ! exists $ ENV { $ _ } ) || exists $ reserved { $ _ } ;
}
2012-03-06 00:42:53 +01:00
}
2010-12-01 19:11:02 +01:00
if ( $ debug ) {
print "PARAMS:\n" ;
my $ value ;
while ( ( $ variable , $ value ) = each % params ) {
2011-04-03 18:56:30 +02:00
print " $variable='$value'\n" unless $ compiler_params { $ variable } ;
2010-12-01 19:11:02 +01:00
}
}
2010-11-07 01:04:17 +01:00
}
2012-12-04 02:18:21 +01:00
2012-12-04 17:49:25 +01:00
add_variables % params ;
2010-11-07 01:04:17 +01:00
}
2011-01-09 22:12:36 +01:00
#
2012-12-04 17:49:25 +01:00
# Add an entry to %param, %variabless and to %compiler_params
2011-01-09 22:12:36 +01:00
#
sub add_param ( $$ ) {
my ( $ param , $ value ) = @ _ ;
2012-12-04 17:49:25 +01:00
$ params { $ param } = $ value ;
$ variables { $ param } = $ value ;
2011-01-09 22:12:36 +01:00
$ compiler_params { $ param } = 1 ;
}
2012-12-04 02:18:21 +01:00
#
2012-12-04 17:49:25 +01:00
# Add variables from a hash
2012-12-04 02:18:21 +01:00
#
2012-12-04 17:49:25 +01:00
sub add_variables ( \% ) {
2012-12-04 02:18:21 +01:00
while ( my ( $ var , $ val ) = each % { $ _ [ 0 ] } ) {
2012-12-04 17:49:25 +01:00
$ variables { $ var } = $ val ;
2012-12-04 02:18:21 +01:00
}
}
2011-01-09 19:12:36 +01:00
#
# emit param=value for each param set in the params file
#
sub export_params () {
2011-01-09 21:14:48 +01:00
my $ count = 0 ;
2012-02-05 19:03:47 +01:00
for my $ param ( sort keys % params ) {
2011-01-14 04:59:17 +01:00
#
# Don't export params added by the compiler
#
next if exists $ compiler_params { $ param } ;
2012-02-05 19:03:47 +01:00
my $ value = $ params { $ param } ;
2011-01-09 19:12:36 +01:00
#
2011-09-11 00:46:26 +02:00
# Values in %params are generated from the output of 'export -p'.
# The different shells have different conventions for delimiting
# the value and for escaping embedded instances of the delimiter.
# The following logic removes the escape characters.
2011-01-09 19:12:36 +01:00
#
2011-09-11 00:46:26 +02:00
if ( $ shell == BASH ) {
$ value =~ s/\\"/"/g ;
} elsif ( $ shell == OLDBASH ) {
$ value =~ s/\\'/'/g ;
} else {
$ value =~ s/'"'"'/'/g ;
2011-01-09 19:12:36 +01:00
}
2011-09-11 00:46:26 +02:00
#
# Don't export pairs from %ENV
#
next if defined $ ENV { $ param } && $ value eq $ ENV { $ param } ;
2011-01-09 21:14:48 +01:00
emit "#\n# From the params file\n#" unless $ count + + ;
2011-09-11 00:46:26 +02:00
#
# We will use double quotes and escape embedded quotes with \.
#
if ( $ value =~ /[\s()['"]/ ) {
$ value =~ s/"/\\"/g ;
2011-01-09 21:14:48 +01:00
emit "$param='$value'" ;
} else {
emit "$param=$value" ;
}
2011-01-09 19:12:36 +01:00
}
}
2012-12-23 19:50:31 +01:00
#
# Walk the CONFIG_PATH converting FORMAT and COMMENT lines to compiler directives
#
2013-12-15 20:23:20 +01:00
sub convert_to_directives () {
2012-12-23 19:50:31 +01:00
my $ sharedir = $ shorewallrc { SHAREDIR } ;
#
# Make a copy of @config_path so that the for-loop below doesn't clobber that list
#
my @ path = @ config_path ;
$ sharedir =~ s | / + $| | ;
my $ dirtest = qr|^$sharedir/+shorewall6?(?:/.*)?$| ;
2015-09-01 20:57:28 +02:00
progress_message3 "Converting 'FORMAT', 'SECTION' and 'COMMENT' lines to compiler directives..." ;
2012-12-23 19:50:31 +01:00
2013-12-15 02:54:10 +01:00
for my $ dir ( @ path ) {
unless ( $ dir =~ /$dirtest/ ) {
if ( ! - w $ dir ) {
warning_message "$dir not processed (not writeable)" ;
} else {
$ dir =~ s | / + $| | ;
opendir ( my $ dirhandle , $ dir ) || fatal_error "Cannot open directory $dir for reading:$!" ;
while ( my $ file = readdir ( $ dirhandle ) ) {
unless ( $ file eq 'capabilities' ||
$ file eq 'params' ||
$ file =~ /^shorewall6?.conf$/ ||
$ file =~ /\.bak$/ ) {
$ file = "$dir/$file" ;
if ( - f $ file && - w _ ) {
#
# writeable regular file
#
2013-05-25 22:20:12 +02:00
my $ result = system << "EOF" ;
2013-12-16 21:31:35 +01:00
perl - pi . bak - e ' /^\\s*FORMAT\\s+/ && s/FORMAT/?FORMAT/ ;
/^\\s*SECTION\\s+/ && s/SECTION/?SECTION/ ;
2013-12-15 20:23:20 +01:00
if ( /^\\s*COMMENT\\s+/ ) {
s/COMMENT/?COMMENT/ ;
} elsif ( /^\\s*COMMENT\\s*\$/ ) {
s/COMMENT/?COMMENT/ ;
} ' $ file
2012-12-23 19:50:31 +01:00
EOF
2013-05-25 22:20:12 +02:00
if ( $ result == 0 ) {
if ( system ( "diff -q $file ${file}.bak > /dev/null" ) ) {
progress_message3 " File $file updated - old file renamed ${file}.bak" ;
} elsif ( rename "${file}.bak" , $ file ) {
2015-09-01 20:57:28 +02:00
progress_message " File $file not updated -- no bare 'COMMENT', 'SECTION' or 'FORMAT' lines found" ;
2013-05-25 22:20:12 +02:00
progress_message " File $file not updated -- no bare 'COMMENT' or 'FORMAT' lines found" ;
} else {
warning message "Unable to rename ${file}.bak to $file:$!" ;
}
} else {
2013-12-15 18:32:09 +01:00
warning_message ( "Unable to update file $file" ) ;
2012-12-23 19:50:31 +01:00
}
} else {
2013-05-25 22:20:12 +02:00
warning_message ( "$file skipped (not writeable)" ) unless - d _ ;
2012-12-23 19:50:31 +01:00
}
}
}
2013-05-25 22:20:12 +02:00
closedir $ dirhandle ;
}
2012-12-23 19:50:31 +01:00
}
}
}
2009-02-22 18:30:14 +01:00
#
2011-09-11 00:46:26 +02:00
# - Process the params file
2009-02-22 18:30:14 +01:00
# - Read the shorewall.conf file
# - Read the capabilities file, if any
2011-09-11 00:46:26 +02:00
# - establish global hashes %params, %config , %globals and %capabilities
2009-02-22 18:30:14 +01:00
#
2015-08-31 23:21:41 +02:00
sub get_configuration ( $$$$ ) {
2009-02-22 18:30:14 +01:00
2015-08-31 23:21:41 +02:00
( my ( $ export , $ update , $ annotate ) , $ checkinline ) = @ _ ;
2009-02-22 18:30:14 +01:00
$ globals { EXPORT } = $ export ;
our ( $ once , @ originalinc ) ;
@ originalinc = @ INC unless $ once + + ;
ensure_config_path ;
2015-07-03 18:38:06 +02:00
my $ default_path = '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' ;
default 'PATH' , $ default_path ;
2015-07-03 23:33:20 +02:00
if ( supplied ( $ ENV { PATH } ) ) {
$ ENV { PATH } . = ":$default_path" ;
} else {
$ ENV { PATH } = $ default_path ;
}
2015-07-03 18:38:06 +02:00
2015-08-27 20:26:26 +02:00
my $ have_capabilities ;
if ( $ export || $> != 0 ) {
#
# Compiling for export or user not root -- must use a capabilties file
# We read it before processing the .conf file so that 'update' has
# the capabilities.
#
unless ( open_file 'capabilities' ) {
fatal_error "The -e compiler option requires a capabilities file" if $ export ;
fatal_error "Compiling under non-root uid requires a capabilities file" ;
}
read_capabilities ;
$ have_capabilities = 1 ;
} elsif ( open_file 'capabilities' ) {
read_capabilities ;
$ have_capabilities = 1 ;
}
2014-10-29 20:22:00 +01:00
get_params ( $ export ) ;
2010-11-07 01:04:17 +01:00
2015-08-31 23:21:41 +02:00
process_shorewall_conf ( $ update , $ annotate ) ;
2009-02-22 18:30:14 +01:00
ensure_config_path ;
@ INC = @ originalinc ;
unshift @ INC , @ config_path ;
2010-01-29 01:39:45 +01:00
#
# get_capabilities requires that the true settings of these options be established
#
2011-02-20 17:52:07 +01:00
default 'MODULE_PREFIX' , 'ko ko.gz o o.gz gz' ;
2014-04-12 20:05:28 +02:00
default_yes_no 'LOAD_HELPERS_ONLY' , 'Yes' ;
2009-02-22 18:30:14 +01:00
2015-08-27 20:26:26 +02:00
if ( ! $ export && $> == 0 ) {
get_capabilities ( $ have_capabilities ) ;
}
2009-02-22 18:30:14 +01:00
2013-04-18 19:30:56 +02:00
my ( $ val , $ all ) ;
2012-08-07 00:54:45 +02:00
2013-04-18 19:30:56 +02:00
if ( supplied ( $ val = $ config { HELPERS } ) ) {
if ( $ val eq 'none' ) {
2013-04-18 20:30:47 +02:00
$ val = '' ;
2013-04-18 19:30:56 +02:00
}
} else {
2013-04-18 20:30:47 +02:00
$ val = join ( ',' , grep $ _ !~ /-0$/ , keys % helpers_enabled ) ;
2013-04-18 19:30:56 +02:00
$ all = 1 ;
}
if ( supplied $ val ) {
my % helpers_temp = % helpers_enabled ;
$ helpers_temp { $ _ } = 0 for keys % helpers_temp ;
my @ helpers = split_list ( $ val , 'helper' ) ;
2013-04-20 01:35:19 +02:00
for ( @ helpers ) {
2013-04-18 19:30:56 +02:00
my $ name = $ _ ;
if ( exists $ helpers_enabled { $ name } ) {
s/-/_/ ;
if ( $ all ) {
$ helpers_temp { $ name } = 1 if have_capability uc ( $ _ ) . '_HELPER' , 1 ;
} else {
require_capability ( uc ( $ _ ) . '_HELPER' , "The $name helper" , 's' ) ;
$ helpers_temp { $ name } = 1 ;
}
} else {
fatal_error "Unknown Helper ($_)" ;
}
}
% helpers_enabled = % helpers_temp ;
while ( my ( $ helper , $ enabled ) = each % helpers_enabled ) {
2013-06-04 21:48:22 +02:00
unless ( $ enabled ) {
$ helper =~ s/-0/0/ ;
$ helper =~ s/-/_/ ;
$ capabilities { uc ( $ helper ) . '_HELPER' } = 0 ;
}
2013-04-18 19:30:56 +02:00
}
} elsif ( have_capability 'CT_TARGET' ) {
$ helpers_enabled { $ _ } = 0 for keys % helpers_enabled ;
$ capabilities { $ _ } = 0 for grep /_HELPER/ , keys % capabilities ;
}
report_capabilities unless $ config { LOAD_HELPERS_ONLY } ;
2012-08-07 00:54:45 +02:00
2013-02-18 17:48:18 +01:00
#
# Now initialize the used capabilities hash
#
% used = ( ) ;
2010-04-25 22:35:41 +02:00
2013-02-18 17:48:18 +01:00
if ( have_capability 'CONNTRACK_MATCH' ) {
2013-07-02 00:36:16 +02:00
$ used { CONNTRACK_MATCH } = REQUIRED ;
2013-02-18 17:48:18 +01:00
} else {
2013-07-02 00:36:16 +02:00
$ used { STATE_MATCH } = REQUIRED ;
2013-02-18 17:48:18 +01:00
}
2012-07-02 20:53:32 +02:00
#
# The following is not documented as it is not likely useful to the user base in general
# Going forward, it allows me to create a configuration that will work on multiple
# Shorewall versions. TME
#
$ config { VERSION } = sprintf "%d%02d%02d" , $ 1 , $ 2 , $ 3 if $ globals { VERSION } =~ /^(\d+)\.(\d+)\.(\d+)/ ;
2010-07-25 21:42:39 +02:00
if ( my $ rate = $ config { LOGLIMIT } ) {
2011-07-22 16:53:30 +02:00
my $ limit ;
2010-07-25 21:42:39 +02:00
2010-07-30 01:50:17 +02:00
if ( $ rate =~ /^[sd]:/ ) {
require_capability 'HASHLIMIT_MATCH' , 'Per-ip log rate limiting' , 's' ;
2010-07-25 21:42:39 +02:00
2011-07-22 16:53:30 +02:00
$ limit = "-m hashlimit " ;
2010-07-25 21:42:39 +02:00
2010-07-30 01:50:17 +02:00
my $ match = have_capability ( 'OLD_HL_MATCH' ) ? 'hashlimit' : 'hashlimit-upto' ;
my $ units ;
2015-08-26 00:55:49 +02:00
if ( $ rate =~ /^[sd]:((\d+)(\/(sec|min|second|minute|hour|day))):(\d+)$/ ) {
2010-07-30 01:50:17 +02:00
fatal_error "Invalid rate ($1)" unless $ 2 ;
fatal_error "Invalid burst value ($5)" unless $ 5 ;
2011-07-22 16:53:30 +02:00
$ limit . = "--$match $1 --hashlimit-burst $5 --hashlimit-name lograte --hashlimit-mode " ;
2010-07-30 01:50:17 +02:00
$ units = $ 4 ;
2015-08-26 22:51:02 +02:00
} elsif ( $ rate =~ /^[sd]:((\d+)(\/(sec|min|second|minute|hour|day))?)$/ ) {
2010-07-30 01:50:17 +02:00
fatal_error "Invalid rate ($1)" unless $ 2 ;
2011-07-22 16:53:30 +02:00
$ limit . = "--$match $1 --hashlimit-name lograte --hashlimit-mode " ;
2010-07-30 01:50:17 +02:00
$ units = $ 4 ;
} else {
fatal_error "Invalid rate ($rate)" ;
2010-07-25 21:42:39 +02:00
}
2010-07-30 01:50:17 +02:00
$ limit . = $ rate =~ /^s:/ ? 'srcip ' : 'dstip ' ;
if ( $ units && $ units ne 'sec' ) {
my $ expire = 60000 ; # 1 minute in milliseconds
2010-09-27 20:16:18 +02:00
2010-07-30 01:50:17 +02:00
if ( $ units ne 'min' ) {
$ expire *= 60 ; #At least an hour
$ expire *= 24 if $ units eq 'day' ;
}
2010-09-27 20:16:18 +02:00
2010-07-30 01:50:17 +02:00
$ limit . = "--hashlimit-htable-expire $expire " ;
}
2015-08-26 00:55:49 +02:00
} elsif ( $ rate =~ /^((\d+)(\/(sec|min|second|minute|hour|day))):(\d+)$/ ) {
2011-07-22 16:53:30 +02:00
fatal_error "Invalid rate ($1)" unless $ 2 ;
fatal_error "Invalid burst value ($5)" unless $ 5 ;
$ limit = "-m limit --limit $1 --limit-burst $5 " ;
2015-08-26 22:51:02 +02:00
} elsif ( $ rate =~ /^(\d+)(\/(sec|min|second|minute|hour|day))?$/ ) {
2011-07-22 16:53:30 +02:00
fatal_error "Invalid rate (${1}${2})" unless $ 1 ;
$ limit = "-m limit --limit $rate " ;
2010-07-30 01:50:17 +02:00
} else {
2011-07-22 16:53:30 +02:00
fatal_error "Invalid rate ($rate)" ;
2010-07-25 21:42:39 +02:00
}
2011-07-22 16:53:30 +02:00
$ globals { LOGLIMIT } = $ limit ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-22 16:53:30 +02:00
$ globals { LOGLIMIT } = '' ;
2009-02-22 18:30:14 +01:00
}
2013-07-02 18:00:36 +02:00
if ( $ globals { LOGLIMIT } ) {
my $ loglimit = $ globals { LOGLIMIT } ;
$ loglimit =~ s/ $// ;
my @ loglimit = ( split ' ' , $ loglimit , 3 ) [ 1 , 2 ] ;
$ globals { LOGILIMIT } = \ @ loglimit ;
2013-07-02 20:47:19 +02:00
} else {
$ globals { LOGILIMIT } = [] ;
2013-07-02 18:00:36 +02:00
}
2009-02-22 18:30:14 +01:00
check_trivalue ( 'IP_FORWARDING' , 'on' ) ;
2010-06-07 16:30:56 +02:00
2010-01-25 19:50:49 +01:00
if ( have_capability ( 'KERNELVERSION' ) < 20631 ) {
2009-12-19 22:47:12 +01:00
check_trivalue ( 'ROUTE_FILTER' , '' ) ;
} else {
2009-12-24 00:13:43 +01:00
$ val = $ config { ROUTE_FILTER } ;
2011-06-18 22:08:26 +02:00
if ( supplied $ val ) {
2009-12-19 22:47:12 +01:00
if ( $ val =~ /\d+/ ) {
fatal_error "Invalid value ($val) for ROUTE_FILTER" unless $ val < 3 ;
} else {
check_trivalue ( 'ROUTE_FILTER' , '' ) ;
}
2009-12-21 00:54:41 +01:00
} else {
check_trivalue ( 'ROUTE_FILTER' , '' ) ;
2009-12-19 22:47:12 +01:00
}
}
if ( $ family == F_IPV6 ) {
2010-06-07 16:30:56 +02:00
$ val = $ config { ROUTE_FILTER } ;
2010-01-11 23:16:03 +01:00
fatal_error "ROUTE_FILTER=$val is not supported in IPv6" if $ val && $ val ne 'off' ;
2009-12-19 22:47:12 +01:00
}
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
check_trivalue ( 'LOG_MARTIANS' , 'on' ) ;
} else {
check_trivalue ( 'LOG_MARTIANS' , 'off' ) ;
fatal_error "LOG_MARTIANS=On is not supported in IPv6" if $ config { LOG_MARTIANS } eq 'on' ;
}
2015-09-06 19:28:44 +02:00
default 'SHOREWALL_SHELL' , '/bin/sh' ;
2009-02-22 18:30:14 +01:00
2015-09-06 19:33:09 +02:00
default 'STARTUP_LOG' , '' ;
2009-02-22 18:30:14 +01:00
if ( $ config { STARTUP_LOG } ne '' ) {
2011-06-18 22:08:26 +02:00
if ( supplied $ config { LOG_VERBOSITY } ) {
2009-02-22 18:30:14 +01:00
if ( $ config { LOG_VERBOSITY } eq '' ) {
$ config { LOG_VERBOSITY } = 2 ;
} else {
my $ val = numeric_value ( $ config { LOG_VERBOSITY } ) ;
fatal_error "Invalid LOG_VERBOSITY ($config{LOG_VERBOSITY} )" unless defined ( $ val ) && ( $ val >= - 1 ) && ( $ val <= 2 ) ;
$ config { STARTUP_LOG } = '' if $ config { LOG_VERBOSITY } < 0 ;
2010-04-07 22:43:57 +02:00
$ config { LOG_VERBOSITY } = $ val ;
2009-02-22 18:30:14 +01:00
}
} else {
$ config { LOG_VERBOSITY } = 2 ;
}
} else {
$ config { LOG_VERBOSITY } = - 1 ;
}
default_yes_no 'ADD_IP_ALIASES' , 'Yes' ;
default_yes_no 'ADD_SNAT_ALIASES' , '' ;
default_yes_no 'DETECT_DNAT_IPADDRS' , '' ;
default_yes_no 'DETECT_DNAT_IPADDRS' , '' ;
default_yes_no 'CLEAR_TC' , $ family == F_IPV4 ? 'Yes' : '' ;
2015-04-01 00:53:05 +02:00
if ( supplied ( $ val = $ config { CLAMPMSS } ) ) {
default_yes_no 'CLAMPMSS' , '' unless $ val =~ /^\d+$/ ;
require_capability 'TCPMSS_TARGET' , "CLAMPMSS=$val" , 's' if $ config { CLAMPMSS } ;
2009-02-22 18:30:14 +01:00
} else {
$ config { CLAMPMSS } = '' ;
}
unless ( $ config { ADD_IP_ALIASES } || $ config { ADD_SNAT_ALIASES } ) {
$ config { RETAIN_ALIASES } = '' ;
} else {
default_yes_no_ipv4 'RETAIN_ALIASES' , '' ;
}
default_yes_no 'ADMINISABSENTMINDED' , '' ;
2009-07-07 03:23:23 +02:00
default_yes_no 'DISABLE_IPV6' , '' ;
2009-02-22 18:30:14 +01:00
2009-09-06 18:51:32 +02:00
unsupported_yes_no_warning 'DYNAMIC_ZONES' ;
unsupported_yes_no 'BRIDGING' ;
unsupported_yes_no_warning 'RFC1918_STRICT' ;
2009-02-22 18:30:14 +01:00
2014-09-28 20:19:41 +02:00
unless ( default_yes_no 'SAVE_IPSETS' , '' , '*' ) {
2014-09-28 23:09:20 +02:00
$ val = $ config { SAVE_IPSETS } ;
2014-09-28 23:38:01 +02:00
unless ( $ val eq 'ipv4' ) {
my @ sets = split_list ( $ val , 'ipset' ) ;
2014-09-28 23:09:20 +02:00
$ globals { SAVED_IPSETS } = \ @ sets ;
require_capability 'IPSET_V5' , 'A saved ipset list' , 's' ;
$ config { SAVE_IPSETS } = '' ;
}
2014-09-28 20:19:41 +02:00
}
2013-01-04 18:17:57 +01:00
default_yes_no 'SAVE_ARPTABLES' , '' ;
2009-02-22 18:30:14 +01:00
default_yes_no 'STARTUP_ENABLED' , 'Yes' ;
default_yes_no 'DELAYBLACKLISTLOAD' , '' ;
2009-09-06 22:37:24 +02:00
default_yes_no 'MAPOLDACTIONS' , 'Yes' ;
2009-02-22 18:30:14 +01:00
2009-06-13 16:07:55 +02:00
warning_message 'DELAYBLACKLISTLOAD=Yes is not supported by Shorewall ' . $ globals { VERSION } if $ config { DELAYBLACKLISTLOAD } ;
2009-02-22 18:30:14 +01:00
default_yes_no 'LOGTAGONLY' , '' ; $ globals { LOGTAGONLY } = $ config { LOGTAGONLY } ;
2009-06-05 19:51:30 +02:00
2009-02-22 18:30:14 +01:00
default_yes_no 'FASTACCEPT' , '' ;
2013-01-30 17:00:47 +01:00
if ( supplied ( $ val = $ config { BLACKLIST } ) ) {
my % states ;
if ( $ val eq 'ALL' ) {
$ globals { BLACKLIST_STATES } = 'ALL' ;
} else {
for ( split_list $ val , 'BLACKLIST' ) {
fatal_error "Invalid BLACKLIST state ($_)" unless /^(?:NEW|RELATED|ESTABLISHED|INVALID|UNTRACKED)$/ ;
fatal_error "Duplicate BLACKLIST state($_)" if $ states { $ _ } ;
$ states { $ _ } = 1 ;
}
fatal_error "ESTABLISHED state may not be specified when FASTACCEPT=Yes" if $ config { FASTACCEPT } && $ states { ESTABLISHED } ;
require_capability 'RAW_TABLE' , 'UNTRACKED state' , 's' if $ states { UNTRACKED } ;
#
# Place the states in a predictable order
#
my @ states ;
for ( qw( NEW ESTABLISHED RELATED INVALID UNTRACKED ) ) {
push @ states , $ _ if $ states { $ _ } ;
}
$ globals { BLACKLIST_STATES } = join ',' , @ states ;
}
} else {
if ( have_capability 'RAW_TABLE' ) {
$ globals { BLACKLIST_STATES } = $ config { FASTACCEPT } ? 'NEW,INVALID,UNTRACKED' : 'NEW,ESTABLISHED,INVALID,UNTRACKED' ;
} else {
$ globals { BLACKLIST_STATES } = $ config { FASTACCEPT } ? 'NEW,INVALID' : 'NEW,INVALID,ESTABLISHED' ;
}
}
2009-02-22 18:30:14 +01:00
default_yes_no 'IMPLICIT_CONTINUE' , '' ;
default_yes_no 'HIGH_ROUTE_MARKS' , '' ;
default_yes_no 'TC_EXPERT' , '' ;
default_yes_no 'USE_ACTIONS' , 'Yes' ;
2009-06-13 16:07:55 +02:00
warning_message 'USE_ACTIONS=No is not supported by Shorewall ' . $ globals { VERSION } unless $ config { USE_ACTIONS } ;
2009-02-22 18:30:14 +01:00
default_yes_no 'EXPORTPARAMS' , '' ;
default_yes_no 'EXPAND_POLICIES' , '' ;
default_yes_no 'KEEP_RT_TABLES' , '' ;
2013-03-24 18:56:38 +01:00
default_yes_no 'USE_RT_NAMES' , '' ;
2009-02-22 18:30:14 +01:00
default_yes_no 'DELETE_THEN_ADD' , 'Yes' ;
2012-12-02 17:26:54 +01:00
default_yes_no 'AUTOCOMMENT' , 'Yes' ;
2009-02-22 18:30:14 +01:00
default_yes_no 'MULTICAST' , '' ;
default_yes_no 'MARK_IN_FORWARD_CHAIN' , '' ;
2013-04-21 16:30:31 +02:00
default_yes_no 'CHAIN_SCRIPTS' , 'Yes' ;
2013-07-24 16:22:51 +02:00
default_yes_no 'TRACK_RULES' , '' ;
2013-12-14 22:35:01 +01:00
default_yes_no 'INLINE_MATCHES' , '' ;
2014-02-05 01:34:03 +01:00
default_yes_no 'BASIC_FILTERS' , '' ;
2015-06-06 21:15:03 +02:00
default_yes_no 'WORKAROUNDS' , 'Yes' ;
2015-10-12 20:45:58 +02:00
if ( supplied ( $ val = $ config { RESTART } ) ) {
fatal_error "Invalid value for RESTART ($val)" unless $ val =~ /^(restart|reload)$/ ;
} elsif ( supplied $ config { LEGACY_RESTART } ) {
default_yes_no 'LEGACY_RESTART' , 'Yes' ;
$ config { RESTART } = $ config { LEGACY_RESTART } ? 'reload' : 'restart' ;
} else {
$ config { RESTART } = 'reload' ;
}
2014-02-05 01:34:03 +01:00
require_capability ( 'BASIC_EMATCH' , 'BASIC_FILTERS=Yes' , 's' ) if $ config { BASIC_FILTERS } ;
2013-07-24 16:22:51 +02:00
2013-09-01 18:14:10 +02:00
if ( $ val = $ config { REJECT_ACTION } ) {
fatal_error "Invalid Reject Action Name ($val)" unless $ val =~ /^[a-zA-Z][\w-]*$/ ;
} else {
$ config { REJECT_ACTION } = '' ;
}
2013-07-24 16:22:51 +02:00
require_capability 'COMMENTS' , 'TRACK_RULES=Yes' , 's' if $ config { TRACK_RULES } ;
2013-02-19 00:15:26 +01:00
default_yes_no 'MANGLE_ENABLED' , have_capability ( 'MANGLE_ENABLED' ) ? 'Yes' : '' ;
2014-04-18 22:22:58 +02:00
default_yes_no 'USE_DEFAULT_RT' , '' ;
2009-02-22 18:30:14 +01:00
default_yes_no 'RESTORE_DEFAULT_ROUTE' , 'Yes' ;
2009-03-31 19:31:23 +02:00
default_yes_no 'AUTOMAKE' , '' ;
2015-08-26 00:55:49 +02:00
default_yes_no 'TRACK_PROVIDERS' , '' ;
2011-05-17 21:51:33 +02:00
2013-03-16 16:20:52 +01:00
unless ( ( $ config { NULL_ROUTE_RFC1918 } || '' ) =~ /^(?:blackhole|unreachable|prohibit)$/ ) {
default_yes_no ( 'NULL_ROUTE_RFC1918' , '' ) ;
$ config { NULL_ROUTE_RFC1918 } = 'blackhole' if $ config { NULL_ROUTE_RFC1918 } ;
}
2011-02-12 21:47:15 +01:00
default_yes_no 'ACCOUNTING' , 'Yes' ;
2010-01-16 18:53:53 +01:00
default_yes_no 'OPTIMIZE_ACCOUNTING' , '' ;
2012-04-24 23:52:57 +02:00
2011-06-18 22:03:55 +02:00
if ( supplied $ config { ACCOUNTING_TABLE } ) {
2011-05-17 21:51:33 +02:00
my $ value = $ config { ACCOUNTING_TABLE } ;
fatal_error "Invalid ACCOUNTING_TABLE setting ($value)" unless $ value eq 'filter' || $ value eq 'mangle' ;
} else {
$ config { ACCOUNTING_TABLE } = 'filter' ;
}
2010-01-16 18:53:53 +01:00
default_yes_no 'DYNAMIC_BLACKLIST' , 'Yes' ;
2010-05-19 16:32:02 +02:00
default_yes_no 'REQUIRE_INTERFACE' , '' ;
2013-02-19 00:15:26 +01:00
default_yes_no 'FORWARD_CLEAR_MARK' , have_capability ( 'MARK' ) ? 'Yes' : '' ;
2010-08-01 17:36:56 +02:00
default_yes_no 'COMPLETE' , '' ;
2011-02-06 17:42:35 +01:00
default_yes_no 'EXPORTMODULES' , '' ;
2011-12-21 01:03:56 +01:00
default_yes_no 'USE_PHYSICAL_NAMES' , '' ;
2012-03-18 21:36:23 +01:00
default_yes_no 'IPSET_WARNINGS' , 'Yes' ;
2012-08-12 16:25:11 +02:00
default_yes_no 'AUTOHELPERS' , 'Yes' ;
2012-10-11 16:34:57 +02:00
default_yes_no 'RESTORE_ROUTEMARKS' , 'Yes' ;
2012-12-12 20:51:31 +01:00
default_yes_no 'IGNOREUNKNOWNVARIABLES' , 'Yes' ;
2012-12-27 18:58:45 +01:00
default_yes_no 'WARNOLDCAPVERSION' , 'Yes' ;
2013-01-13 22:23:38 +01:00
default_yes_no 'DEFER_DNS_RESOLUTION' , 'Yes' ;
2012-08-03 19:53:20 +02:00
2012-11-09 17:54:54 +01:00
$ config { IPSET } = '' if supplied $ config { IPSET } && $ config { IPSET } eq 'ipset' ;
2011-06-24 15:22:16 +02:00
require_capability 'MARK' , 'FORWARD_CLEAR_MARK=Yes' , 's' , if $ config { FORWARD_CLEAR_MARK } ;
2009-02-22 18:30:14 +01:00
2015-08-26 00:55:49 +02:00
numeric_option 'TC_BITS' , 8 , 0 ;
numeric_option 'MASK_BITS' , 8 , 0 ;
numeric_option 'PROVIDER_OFFSET' , 0 , 0 ;
2015-08-21 21:42:19 +02:00
numeric_option 'PROVIDER_BITS' , 8 , 0 ;
2011-11-17 19:40:47 +01:00
numeric_option 'ZONE_BITS' , 0 , 0 ;
2010-06-07 16:30:56 +02:00
2011-11-18 16:23:24 +01:00
require_capability 'MARK_ANYWHERE' , 'A non-zero ZONE_BITS setting' , 's' if $ config { ZONE_BITS } ;
2011-11-18 01:07:45 +01:00
2010-01-11 23:16:03 +01:00
if ( $ config { PROVIDER_OFFSET } ) {
2011-11-17 19:40:47 +01:00
$ config { PROVIDER_OFFSET } = $ config { MASK_BITS } if $ config { PROVIDER_OFFSET } < $ config { MASK_BITS } ;
$ globals { ZONE_OFFSET } = $ config { PROVIDER_OFFSET } + $ config { PROVIDER_BITS } ;
2010-08-28 17:29:47 +02:00
} elsif ( $ config { MASK_BITS } >= $ config { PROVIDER_BITS } ) {
2011-11-17 19:40:47 +01:00
$ globals { ZONE_OFFSET } = $ config { MASK_BITS } ;
2010-08-27 19:09:42 +02:00
} else {
2011-11-17 19:40:47 +01:00
$ globals { ZONE_OFFSET } = $ config { PROVIDER_BITS } ;
2010-01-11 23:16:03 +01:00
}
2013-07-10 22:27:58 +02:00
#
2013-07-11 19:39:21 +02:00
# It is okay if the event mark is outside of the a 32-bit integer. We check that in IfEvent"
2013-07-10 22:27:58 +02:00
#
2012-05-10 16:25:07 +02:00
fatal_error 'Invalid Packet Mark layout' if $ config { ZONE_BITS } + $ globals { ZONE_OFFSET } > 30 ;
2012-04-24 23:52:57 +02:00
2011-11-17 19:40:47 +01:00
$ globals { EXCLUSION_MASK } = 1 << ( $ globals { ZONE_OFFSET } + $ config { ZONE_BITS } ) ;
2012-05-10 20:19:23 +02:00
$ globals { TPROXY_MARK } = $ globals { EXCLUSION_MASK } << 1 ;
2013-07-11 19:39:21 +02:00
$ globals { EVENT_MARK } = $ globals { TPROXY_MARK } << 1 ;
2011-11-17 19:40:47 +01:00
$ globals { PROVIDER_MIN } = 1 << $ config { PROVIDER_OFFSET } ;
$ globals { TC_MAX } = make_mask ( $ config { TC_BITS } ) ;
$ globals { TC_MASK } = make_mask ( $ config { MASK_BITS } ) ;
$ globals { PROVIDER_MASK } = make_mask ( $ config { PROVIDER_BITS } ) << $ config { PROVIDER_OFFSET } ;
if ( $ config { ZONE_BITS } ) {
2012-09-02 20:06:28 +02:00
$ globals { ZONE_MASK } = make_mask ( $ config { ZONE_BITS } ) << $ globals { ZONE_OFFSET } ;
2011-11-17 19:40:47 +01:00
} else {
2012-09-02 20:06:28 +02:00
$ globals { ZONE_MASK } = 0 ;
2011-11-17 19:40:47 +01:00
}
2010-01-11 23:16:03 +01:00
2010-07-27 20:02:36 +02:00
if ( ( my $ userbits = $ config { PROVIDER_OFFSET } - $ config { TC_BITS } ) > 0 ) {
$ globals { USER_MASK } = make_mask ( $ userbits ) << $ config { TC_BITS } ;
2012-06-23 16:57:39 +02:00
$ globals { USER_BITS } = $ userbits ;
2010-07-27 20:02:36 +02:00
} else {
2012-06-23 16:57:39 +02:00
$ globals { USER_MASK } = $ globals { USER_BITS } = 0 ;
2010-07-27 20:02:36 +02:00
}
2015-09-07 20:29:24 +02:00
$ val = $ config { PROVIDER_OFFSET } ;
2015-09-07 22:10:44 +02:00
$ globals { SMALL_MAX } = $ val ? make_mask ( $ val ) : $ globals { TC_MASK } ;
2015-09-07 20:29:24 +02:00
2011-06-18 22:03:55 +02:00
if ( supplied ( $ val = $ config { ZONE2ZONE } ) ) {
2009-11-10 23:12:55 +01:00
fatal_error "Invalid ZONE2ZONE value ( $val )" unless $ val =~ /^[2-]$/ ;
} else {
2013-11-24 17:16:28 +01:00
$ config { ZONE2ZONE } = '-' ;
2009-11-10 23:12:55 +01:00
}
default 'BLACKLIST_DISPOSITION' , 'DROP' ;
2009-02-22 18:30:14 +01:00
2011-05-21 18:25:58 +02:00
unless ( ( $ val = $ config { BLACKLIST_DISPOSITION } ) =~ /^(?:A_)?DROP$/ || $ config { BLACKLIST_DISPOSITION } =~ /^(?:A_)?REJECT/ ) {
2011-05-20 16:47:35 +02:00
fatal_error q( BLACKLIST_DISPOSITION must be 'DROP', 'A_DROP', 'REJECT' or 'A_REJECT' ) ;
2010-12-30 03:43:14 +01:00
}
2011-05-21 18:25:58 +02:00
require_capability 'AUDIT_TARGET' , "BLACKLIST_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
2011-05-22 00:02:04 +02:00
default 'SMURF_DISPOSITION' , 'DROP' ;
unless ( ( $ val = $ config { SMURF_DISPOSITION } ) =~ /^(?:A_)?DROP$/ ) {
fatal_error q( SMURF_DISPOSITION must be 'DROP' or 'A_DROP' ) ;
}
require_capability 'AUDIT_TARGET' , "SMURF_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
2013-02-12 16:47:02 +01:00
default_log_level 'BLACKLIST_LOG_LEVEL' , '' ;
default_log_level 'MACLIST_LOG_LEVEL' , '' ;
default_log_level 'TCP_FLAGS_LOG_LEVEL' , '' ;
default_log_level 'RFC1918_LOG_LEVEL' , '' ;
default_log_level 'RELATED_LOG_LEVEL' , '' ;
default_log_level 'INVALID_LOG_LEVEL' , '' ;
default_log_level 'UNTRACKED_LOG_LEVEL' , '' ;
2009-06-05 19:51:30 +02:00
2014-10-07 16:34:55 +02:00
if ( supplied ( $ val = $ config { LOG_BACKEND } ) ) {
2014-09-25 00:26:13 +02:00
if ( $ family == F_IPV4 && $ val eq 'ULOG' ) {
2014-09-25 01:35:41 +02:00
$ val = 'ipt_ULOG' ;
2014-09-25 00:26:13 +02:00
} elsif ( $ val eq 'netlink' ) {
$ val = 'nfnetlink_log' ;
} elsif ( $ val eq 'LOG' ) {
2014-11-15 17:56:42 +01:00
$ val = $ family == F_IPV4 ? 'ipt_LOG' : 'ip6t_LOG' ;
2014-09-25 00:26:13 +02:00
} else {
fatal_error "Invalid LOG Backend ($val)" ;
}
$ config { LOG_BACKEND } = $ val ;
}
2009-06-05 19:51:30 +02:00
warning_message "RFC1918_LOG_LEVEL=$config{RFC1918_LOG_LEVEL} ignored. The 'norfc1918' interface/host option is no longer supported" if $ config { RFC1918_LOG_LEVEL } ;
2009-02-22 18:30:14 +01:00
default_log_level 'SMURF_LOG_LEVEL' , '' ;
default_log_level 'LOGALLNEW' , '' ;
2011-05-28 04:42:09 +02:00
default_log_level 'SFILTER_LOG_LEVEL' , 'info' ;
2012-04-24 23:52:57 +02:00
2011-05-28 04:42:09 +02:00
if ( $ val = $ config { SFILTER_DISPOSITION } ) {
fatal_error "Invalid SFILTER_DISPOSITION setting ($val)" unless $ val =~ /^(A_)?(DROP|REJECT)$/ ;
require_capability 'AUDIT_TARGET' , "SFILTER_DISPOSITION=$val" , 's' if $ 1 ;
2011-05-25 02:07:31 +02:00
} else {
2011-05-28 04:42:09 +02:00
$ config { SFILTER_DISPOSITION } = 'DROP' ;
2011-05-25 02:07:31 +02:00
}
2012-07-15 19:05:32 +02:00
default_log_level 'RPFILTER_LOG_LEVEL' , 'info' ;
if ( $ val = $ config { RPFILTER_DISPOSITION } ) {
fatal_error "Invalid RPFILTER_DISPOSITION setting ($val)" unless $ val =~ /^(A_)?(DROP|REJECT)$/ ;
require_capability 'AUDIT_TARGET' , "RPFILTER_DISPOSITION=$val" , 's' if $ 1 ;
} else {
$ config { RPFILTER_DISPOSITION } = 'DROP' ;
}
2009-02-22 18:30:14 +01:00
if ( $ val = $ config { MACLIST_DISPOSITION } ) {
2011-05-20 17:33:36 +02:00
if ( $ val =~ /^(?:A_)?DROP$/ ) {
$ globals { MACLIST_TARGET } = $ val ;
2011-05-20 16:47:35 +02:00
} elsif ( $ val eq 'REJECT' ) {
$ globals { MACLIST_TARGET } = 'reject' ;
} elsif ( $ val eq 'A_REJECT' ) {
$ globals { MACLIST_TARGET } = $ val ;
} elsif ( $ val eq 'ACCEPT' ) {
$ globals { MACLIST_TARGET } = 'RETURN' ;
} else {
fatal_error "Invalid value ($config{MACLIST_DISPOSITION}) for MACLIST_DISPOSITION"
2009-02-22 18:30:14 +01:00
}
2011-05-21 18:25:58 +02:00
require_capability 'AUDIT_TARGET' , "MACLIST_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
2009-02-22 18:30:14 +01:00
} else {
2011-05-30 17:49:41 +02:00
$ config { MACLIST_DISPOSITION } = 'REJECT' ;
$ globals { MACLIST_TARGET } = 'reject' ;
2009-02-22 18:30:14 +01:00
}
2011-12-06 01:08:17 +01:00
if ( $ val = $ config { RELATED_DISPOSITION } ) {
if ( $ val =~ /^(?:A_)?(?:DROP|ACCEPT)$/ ) {
$ globals { RELATED_TARGET } = $ val ;
} elsif ( $ val eq 'REJECT' ) {
$ globals { RELATED_TARGET } = 'reject' ;
} elsif ( $ val eq 'A_REJECT' ) {
$ globals { RELATED_TARGET } = $ val ;
2013-01-28 20:47:45 +01:00
} elsif ( $ val eq 'CONTINUE' ) {
$ globals { RELATED_TARGET } = '' ;
2011-12-06 01:08:17 +01:00
} else {
2011-12-23 00:51:50 +01:00
fatal_error "Invalid value ($config{RELATED_DISPOSITION}) for RELATED_DISPOSITION"
2011-12-06 01:08:17 +01:00
}
2013-01-24 17:33:59 +01:00
require_capability 'AUDIT_TARGET' , "RELATED_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
2011-12-06 01:08:17 +01:00
} else {
$ config { RELATED_DISPOSITION } =
$ globals { RELATED_TARGET } = 'ACCEPT' ;
}
2013-01-24 17:33:59 +01:00
if ( $ val = $ config { INVALID_DISPOSITION } ) {
2013-02-02 18:30:25 +01:00
if ( $ val =~ /^(?:A_)?DROP$/ ) {
2013-01-24 17:33:59 +01:00
$ globals { INVALID_TARGET } = $ val ;
} elsif ( $ val eq 'REJECT' ) {
$ globals { INVALID_TARGET } = 'reject' ;
} elsif ( $ val eq 'A_REJECT' ) {
$ globals { INVALID_TARGET } = $ val ;
} elsif ( $ val eq 'CONTINUE' ) {
$ globals { INVALID_TARGET } = '' ;
} else {
fatal_error "Invalid value ($config{INVALID_DISPOSITION}) for INVALID_DISPOSITION"
}
2013-01-25 00:42:01 +01:00
require_capability 'AUDIT_TARGET' , "INVALID_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
2013-01-24 17:33:59 +01:00
} else {
$ config { INVALID_DISPOSITION } = 'CONTINUE' ;
$ globals { INVALID_TARGET } = '' ;
}
2013-01-25 00:42:01 +01:00
if ( $ val = $ config { UNTRACKED_DISPOSITION } ) {
if ( $ val =~ /^(?:A_)?(?:DROP|ACCEPT)$/ ) {
$ globals { UNTRACKED_TARGET } = $ val ;
} elsif ( $ val eq 'REJECT' ) {
$ globals { UNTRACKED_TARGET } = 'reject' ;
} elsif ( $ val eq 'A_REJECT' ) {
$ globals { UNTRACKED_TARGET } = $ val ;
2013-01-27 17:12:49 +01:00
} elsif ( $ val eq 'CONTINUE' ) {
$ globals { UNTRACKED_TARGET } = '' ;
2013-01-25 00:42:01 +01:00
} else {
fatal_error "Invalid value ($config{UNTRACKED_DISPOSITION}) for UNTRACKED_DISPOSITION"
}
require_capability 'AUDIT_TARGET' , "UNTRACKED_DISPOSITION=$val" , 's' if $ val =~ /^A_/ ;
} else {
$ config { UNTRACKED_DISPOSITION } = 'CONTINUE' ;
$ globals { UNTRACKED_TARGET } = '' ;
}
2009-02-22 18:30:14 +01:00
if ( $ val = $ config { MACLIST_TABLE } ) {
if ( $ val eq 'mangle' ) {
2011-05-20 16:47:35 +02:00
fatal_error 'MACLIST_DISPOSITION=$1 is not allowed with MACLIST_TABLE=mangle' if $ config { MACLIST_DISPOSITION } =~ /^((?:A)?REJECT)$/ ;
2009-02-22 18:30:14 +01:00
} else {
fatal_error "Invalid value ($val) for MACLIST_TABLE option" unless $ val eq 'filter' ;
}
} else {
default 'MACLIST_TABLE' , 'filter' ;
}
if ( $ val = $ config { TCP_FLAGS_DISPOSITION } ) {
2011-07-30 15:57:18 +02:00
fatal_error "Invalid value ($config{TCP_FLAGS_DISPOSITION}) for TCP_FLAGS_DISPOSITION" unless $ val =~ /^(?:(A_)?(?:REJECT|DROP))|ACCEPT$/ ;
require_capability 'AUDIT_TARGET' , "TCP_FLAGS_DISPOSITION=$val" , 's' if $ 1 ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-29 00:56:34 +02:00
$ val = $ config { TCP_FLAGS_DISPOSITION } = 'DROP' ;
2009-02-22 18:30:14 +01:00
}
default 'TC_ENABLED' , $ family == F_IPV4 ? 'Internal' : 'no' ;
$ val = "\L$config{TC_ENABLED}" ;
if ( $ val eq 'yes' ) {
my $ file = find_file 'tcstart' ;
fatal_error "Unable to find tcstart file" unless - f $ file ;
$ globals { TC_SCRIPT } = $ file ;
} elsif ( $ val eq 'internal' ) {
$ config { TC_ENABLED } = 'Internal' ;
2010-11-14 16:52:51 +01:00
} elsif ( $ val eq 'shared' ) {
$ config { TC_ENABLED } = 'Shared' ;
2010-01-13 02:01:20 +01:00
} elsif ( $ val eq 'simple' ) {
$ config { TC_ENABLED } = 'Simple' ;
2009-02-22 18:30:14 +01:00
} else {
fatal_error "Invalid value ($config{TC_ENABLED}) for TC_ENABLED" unless $ val eq 'no' ;
$ config { TC_ENABLED } = '' ;
}
2010-01-11 23:16:03 +01:00
if ( $ config { TC_ENABLED } ) {
fatal_error "TC_ENABLED=$config{TC_ENABLED} is not allowed with MANGLE_ENABLED=No" unless $ config { MANGLE_ENABLED } ;
require_capability 'MANGLE_ENABLED' , "TC_ENABLED=$config{TC_ENABLED}" , 's' ;
}
2009-02-22 18:30:14 +01:00
2010-01-13 02:01:20 +01:00
if ( $ val = $ config { TC_PRIOMAP } ) {
my @ priomap = split ' ' , $ val ;
fatal_error "Invalid TC_PRIOMAP ($val)" unless @ priomap == 16 ;
for ( @ priomap ) {
2011-03-17 00:42:40 +01:00
fatal_error "Invalid TC_PRIOMAP entry ($_)" unless /^[1-3]$/ ;
2010-01-13 02:01:20 +01:00
$ _ - - ;
}
$ config { TC_PRIOMAP } = join ' ' , @ priomap ;
} else {
$ config { TC_PRIOMAP } = '1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1' ;
}
2009-02-22 18:30:14 +01:00
default 'RESTOREFILE' , 'restore' ;
default 'DROP_DEFAULT' , 'Drop' ;
default 'REJECT_DEFAULT' , 'Reject' ;
default 'QUEUE_DEFAULT' , 'none' ;
default 'NFQUEUE_DEFAULT' , 'none' ;
default 'ACCEPT_DEFAULT' , 'none' ;
default 'OPTIMIZE' , 0 ;
2011-06-13 15:39:38 +02:00
for my $ default ( qw/DROP_DEFAULT REJECT_DEFAULT QUEUE_DEFAULT NFQUEUE_DEFAULT ACCEPT_DEFAULT/ ) {
2009-02-22 18:30:14 +01:00
$ config { $ default } = 'none' if "\L$config{$default}" eq 'none' ;
}
2013-07-29 19:08:35 +02:00
if ( ( $ val = $ config { OPTIMIZE } ) =~ /^all$/i ) {
$ config { OPTIMIZE } = $ val = OPTIMIZE_ALL ;
} elsif ( $ val =~ /^none$/i ) {
$ config { OPTIMIZE } = $ val = 0 ;
} else {
$ val = numeric_value $ config { OPTIMIZE } ;
2009-02-22 18:30:14 +01:00
2013-07-29 19:08:35 +02:00
fatal_error "Invalid OPTIMIZE value ($config{OPTIMIZE})" unless supplied ( $ val ) && $ val >= 0 && ( $ val & ~ OPTIMIZE_USE_FIRST ) <= OPTIMIZE_ALL ;
}
2009-02-22 18:30:14 +01:00
2011-11-24 19:57:09 +01:00
require_capability 'XMULTIPORT' , 'OPTIMIZE level 16' , 's' if $ val & 16 ;
2009-02-22 18:30:14 +01:00
$ globals { MARKING_CHAIN } = $ config { MARK_IN_FORWARD_CHAIN } ? 'tcfor' : 'tcpre' ;
if ( $ val = $ config { LOGFORMAT } ) {
my $ result ;
eval {
if ( $ val =~ /%d/ ) {
$ globals { LOGRULENUMBERS } = 'Yes' ;
$ result = sprintf "$val" , 'fooxx2barxx' , 1 , 'ACCEPT' ;
} else {
$ result = sprintf "$val" , 'fooxx2barxx' , 'ACCEPT' ;
}
} ;
fatal_error "Invalid LOGFORMAT ($val)" if $@ ;
fatal_error "LOGFORMAT string is longer than 29 characters ($val)" if length $ result > 29 ;
$ globals { MAXZONENAMELENGTH } = int ( 5 + ( ( 29 - ( length $ result ) ) / 2 ) ) ;
} else {
$ config { LOGFORMAT } = 'Shorewall:%s:%s:' ;
$ globals { MAXZONENAMELENGTH } = 5 ;
}
if ( $ config { LOCKFILE } ) {
my ( $ file , $ dir , $ suffix ) ;
eval {
( $ file , $ dir , $ suffix ) = fileparse ( $ config { LOCKFILE } ) ;
} ;
2009-08-26 19:34:04 +02:00
cleanup , die $@ if $@ ;
2009-02-22 18:30:14 +01:00
fatal_error "LOCKFILE=$config{LOCKFILE}: Directory $dir does not exist" unless $ export or - d $ dir ;
} else {
$ config { LOCKFILE } = '' ;
}
2012-01-17 16:24:12 +01:00
require_capability ( 'MULTIPORT' , "Shorewall $globals{VERSION}" , 's' ) ;
require_capability ( 'RECENT_MATCH' , 'MACLIST_TTL' , 's' ) if $ config { MACLIST_TTL } ;
require_capability ( 'XCONNMARK' , 'HIGH_ROUTE_MARKS=Yes' , 's' ) if $ config { PROVIDER_OFFSET } > 0 ;
require_capability ( 'MANGLE_ENABLED' , 'Traffic Shaping' , 's' ) if $ config { TC_ENABLED } ;
2009-02-22 18:30:14 +01:00
2012-12-27 18:58:45 +01:00
if ( $ config { WARNOLDCAPVERSION } ) {
2012-12-27 00:48:08 +01:00
if ( $ capabilities { CAPVERSION } ) {
warning_message "Your capabilities file is out of date -- it does not contain all of the capabilities defined by $Product version $globals{VERSION}"
unless $ capabilities { CAPVERSION } >= $ globals { CAPVERSION } ;
} else {
warning_message "Your capabilities file may not contain all of the capabilities defined by $Product version $globals{VERSION}" ;
}
}
2012-12-04 17:49:25 +01:00
add_variables % config ;
2012-12-04 02:18:21 +01:00
while ( my ( $ var , $ val ) = each % renamed ) {
2012-12-04 17:49:25 +01:00
$ variables { $ var } = $ config { $ val } ;
2012-12-04 02:18:21 +01:00
}
2012-12-23 19:50:31 +01:00
2015-08-31 23:21:41 +02:00
convert_to_directives if $ update ;
2013-05-01 23:48:27 +02:00
cleanup_iptables if $ sillyname && ! $ config { LOAD_HELPERS_ONLY } ;
2012-12-04 02:18:21 +01:00
}
2012-12-23 19:50:31 +01:00
2009-02-22 18:30:14 +01:00
#
2009-10-06 00:43:29 +02:00
# The values of the options in @propagateconfig are copied to the script file in OPTION=<value> format.
2009-02-22 18:30:14 +01:00
#
sub propagateconfig () {
for my $ option ( @ propagateconfig ) {
2010-04-07 23:38:29 +02:00
my $ value = $ config { $ option } ;
$ value = '' unless defined $ value ;
2009-02-22 18:30:14 +01:00
emit "$option=\"$value\"" ;
}
}
#
# Add a shell script file to the output script -- Return true if the
2009-06-29 17:14:53 +02:00
# file exists and is not in /usr/share/shorewall/ and is non-empty.
2009-02-22 18:30:14 +01:00
#
2010-10-01 22:20:36 +02:00
sub append_file ( $;$$ ) {
my ( $ file , $ nomsg , $ unindented ) = @ _ ;
my $ user_exit = find_file $ file ;
2009-02-22 18:30:14 +01:00
my $ result = 0 ;
2010-10-01 22:20:36 +02:00
my $ save_indent = $ indent ;
2012-04-24 23:52:57 +02:00
2010-10-01 22:20:36 +02:00
$ indent = '' if $ unindented ;
2009-02-22 18:30:14 +01:00
2012-05-07 02:30:17 +02:00
unless ( $ user_exit =~ m (^$shorewallrc{SHAREDIR}/shorewall6?/) ) {
2009-02-22 18:30:14 +01:00
if ( - f $ user_exit ) {
2010-10-01 22:20:36 +02:00
if ( $ nomsg ) {
2009-06-29 17:14:53 +02:00
#
# Suppress progress message
#
$ result = copy1 $ user_exit ;
} else {
#
# Include progress message -- Pretend progress_message call was in the file
2009-08-20 23:32:15 +02:00
#
2012-03-20 15:33:32 +01:00
my $ name = $ globals { EXPORT } ? "$file user exit" : $ user_exit ;
2009-06-29 17:14:53 +02:00
$ result = 1 ;
2012-03-20 15:33:32 +01:00
save_progress_message "Processing $name ..." ;
2009-06-29 17:14:53 +02:00
copy1 $ user_exit ;
}
2009-02-22 18:30:14 +01:00
}
}
2010-10-01 22:20:36 +02:00
$ indent = $ save_indent ;
2009-02-22 18:30:14 +01:00
$ result ;
}
#
# Run a Perl extension script
#
sub run_user_exit ( $ ) {
my $ chainref = $ _ [ 0 ] ;
my $ file = find_file $ chainref - > { name } ;
2013-04-21 16:30:31 +02:00
if ( $ config { CHAIN_SCRIPTS } && - f $ file ) {
2010-12-31 23:19:31 +01:00
progress_message2 "Running $file..." ;
2009-02-22 18:30:14 +01:00
my $ command = qq( package Shorewall::User;\nno strict;\n# line 1 "$file"\n ) . `cat $file` ;
unless ( my $ return = eval $ command ) {
fatal_error "Couldn't parse $file: $@" if $@ ;
unless ( defined $ return ) {
2009-08-20 23:32:15 +02:00
fatal_error "Couldn't do $file: $!" if $! ;
2009-02-22 18:30:14 +01:00
fatal_error "Couldn't do $file" ;
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
fatal_error "$file returned a false value" ;
}
}
}
sub run_user_exit1 ( $ ) {
my $ file = find_file $ _ [ 0 ] ;
if ( - f $ file ) {
2010-12-31 23:19:31 +01:00
progress_message2 "Running $file..." ;
2009-02-22 18:30:14 +01:00
#
# File may be empty -- in which case eval would fail
#
push_open $ file ;
2012-04-11 02:01:38 +02:00
if ( read_a_line ( STRIP_COMMENTS | SUPPRESS_WHITESPACE | CHECK_GUNK ) ) {
2009-02-22 18:30:14 +01:00
close_file ;
2012-05-05 19:31:55 +02:00
pop_open ;
2009-02-22 18:30:14 +01:00
my $ command = qq( package Shorewall::User;\n# line 1 "$file"\n ) . `cat $file` ;
unless ( my $ return = eval $ command ) {
fatal_error "Couldn't parse $file: $@" if $@ ;
unless ( defined $ return ) {
fatal_error "Couldn't do $file: $!" if $! ;
fatal_error "Couldn't do $file" ;
}
fatal_error "$file returned a false value" ;
}
} else {
pop_open ;
}
}
}
sub run_user_exit2 ( $$ ) {
my ( $ file , $ chainref ) = ( find_file $ _ [ 0 ] , $ _ [ 1 ] ) ;
2013-04-21 16:30:31 +02:00
if ( $ config { CHAIN_SCRIPTS } && - f $ file ) {
2010-12-31 23:19:31 +01:00
progress_message2 "Running $file..." ;
2009-02-22 18:30:14 +01:00
#
# File may be empty -- in which case eval would fail
#
push_open $ file ;
2012-04-11 02:01:38 +02:00
if ( read_a_line ( STRIP_COMMENTS | SUPPRESS_WHITESPACE | CHECK_GUNK ) ) {
2009-02-22 18:30:14 +01:00
close_file ;
2012-05-05 19:31:55 +02:00
pop_open ;
2009-02-22 18:30:14 +01:00
unless ( my $ return = eval `cat $file` ) {
fatal_error "Couldn't parse $file: $@" if $@ ;
unless ( defined $ return ) {
fatal_error "Couldn't do $file: $!" if $! ;
fatal_error "Couldn't do $file" ;
}
fatal_error "$file returned a false value" ;
}
}
pop_open ;
}
}
#
# Generate the aux config file for Shorewall Lite
#
sub generate_aux_config () {
sub conditionally_add_option ( $ ) {
my $ option = $ _ [ 0 ] ;
my $ value = $ config { $ option } ;
2011-06-12 01:14:31 +02:00
emit "[ -n \"\${$option:=$value}\" ]" if supplied $ value ;
2009-02-22 18:30:14 +01:00
}
sub conditionally_add_option1 ( $ ) {
my $ option = $ _ [ 0 ] ;
my $ value = $ config { $ option } ;
emit "$option=\"$value\"" if $ value ;
}
create_temp_aux_config ;
my $ date = localtime ;
2009-06-13 16:07:55 +02:00
emit "#\n# Shorewall auxiliary configuration file created by Shorewall version $globals{VERSION} - $date\n#" ;
2009-02-22 18:30:14 +01:00
2015-10-12 20:45:58 +02:00
for my $ option ( qw( VERBOSITY LOGFILE LOGFORMAT ARPTABLES IPTABLES IP6TABLES IP TC IPSET PATH SHOREWALL_SHELL SUBSYSLOCK LOCKFILE RESTOREFILE WORKAROUNDS RESTART ) ) {
2009-02-22 18:30:14 +01:00
conditionally_add_option $ option ;
}
conditionally_add_option1 'TC_ENABLED' ;
2010-10-03 19:56:55 +02:00
my $ fn = find_file 'scfilter' ;
if ( - f $ fn ) {
emit ( '' ,
2010-10-03 21:52:30 +02:00
'show_connections_filter() {' ) ;
push_indent ;
append_file ( $ fn , 1 ) or emit 'cat -' ;
pop_indent ;
emit '}' ;
2010-10-03 19:56:55 +02:00
}
2009-02-22 18:30:14 +01:00
2010-10-19 17:42:35 +02:00
$ fn = find_file 'dumpfilter' ;
2010-10-07 23:19:09 +02:00
if ( - f $ fn ) {
emit ( '' ,
'dump_filter() {' ) ;
push_indent ;
append_file ( $ fn , 1 ) or emit 'cat -' ;
pop_indent ;
emit '}' ;
}
2010-10-03 19:56:55 +02:00
finalize_aux_config ;
2009-02-22 18:30:14 +01:00
}
2011-11-20 21:29:17 +01:00
sub dump_mark_layout () {
sub dumpout ( $$$$$ ) {
my ( $ name , $ bits , $ min , $ max , $ mask ) = @ _ ;
if ( $ bits ) {
if ( $ min == $ max ) {
emit_unindented "$name:" . $ min . ' mask ' . in_hex ( $ mask ) ;
} else {
emit_unindented "$name:" . join ( '-' , $ min , $ max ) . ' (' . join ( '-' , in_hex ( $ min ) , in_hex ( $ max ) ) . ') mask ' . in_hex ( $ mask ) ;
}
} else {
emit_unindented "$name: Not Enabled" ;
}
}
dumpout ( "Traffic Shaping" ,
$ config { TC_BITS } ,
0 ,
$ globals { TC_MAX } ,
$ globals { TC_MASK } ) ;
dumpout ( "User" ,
2012-06-23 16:57:39 +02:00
$ globals { USER_BITS } ,
2011-11-20 21:29:17 +01:00
$ globals { TC_MAX } + 1 ,
$ globals { USER_MASK } ,
$ globals { USER_MASK } ) ;
2012-04-24 23:52:57 +02:00
2011-11-20 21:29:17 +01:00
dumpout ( "Provider" ,
$ config { PROVIDER_BITS } ,
$ globals { PROVIDER_MIN } ,
$ globals { PROVIDER_MASK } ,
$ globals { PROVIDER_MASK } ) ;
dumpout ( "Zone" ,
$ config { ZONE_BITS } ,
1 << $ globals { ZONE_OFFSET } ,
$ globals { ZONE_MASK } ,
$ globals { ZONE_MASK } ) ;
dumpout ( "Exclusion" ,
1 ,
$ globals { EXCLUSION_MASK } ,
$ globals { EXCLUSION_MASK } ,
$ globals { EXCLUSION_MASK } ) ;
2012-06-23 16:57:39 +02:00
dumpout ( "TProxy" ,
1 ,
$ globals { TPROXY_MARK } ,
$ globals { TPROXY_MARK } ,
$ globals { TPROXY_MARK } ) ;
2012-04-24 23:52:57 +02:00
}
2011-11-20 21:29:17 +01:00
2013-02-18 17:48:18 +01:00
sub report_used_capabilities () {
if ( $ verbosity > 1 ) {
progress_message2 "Configuration uses these capabilities ('*' denotes required):" ;
for ( sort grep $ _ ne 'KERNELVERSION' , keys % used ) {
2013-07-02 00:36:16 +02:00
if ( ( $ used { $ _ } || 0 ) & REQUIRED ) {
2013-02-18 17:48:18 +01:00
progress_message2 " $_*" ;
} else {
progress_message2 " $_" ;
}
}
}
}
2009-02-22 18:30:14 +01:00
END {
2009-08-26 19:34:04 +02:00
cleanup ;
2009-02-22 18:30:14 +01:00
}
1 ;