summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohit Mehta <mohit@vyatta.com>2011-12-01 05:33:44 -0800
committerMohit Mehta <mohit@vyatta.com>2011-12-01 05:33:44 -0800
commit25364db4c400b2a05bbfca65e98f8b27271f962f (patch)
tree7408500e09cbc06d7909ae301611f4e198a8e05a
parentd5d88ed8f5323361f938a8f0b7454a8c73dd6c12 (diff)
downloadvyatta-cfg-firewall-25364db4c400b2a05bbfca65e98f8b27271f962f.tar.gz
vyatta-cfg-firewall-25364db4c400b2a05bbfca65e98f8b27271f962f.zip
Bug 6063 ENH: Provide option(s) to globally allow stateful return traffic
* add code to set global policy for established, related, invalid states
-rw-r--r--Makefile.am1
-rwxr-xr-xlib/Vyatta/IpTables/Mgr.pm142
-rw-r--r--scripts/firewall/firewall.init.in45
-rwxr-xr-xscripts/firewall/vyatta-firewall.pl8
-rwxr-xr-xscripts/firewall/vyatta-fw-global-state-policy.pl304
-rw-r--r--templates/firewall/ipv6-modify/node.tag/rule/node.tag/log/node.def4
-rw-r--r--templates/firewall/ipv6-name/node.tag/rule/node.tag/log/node.def4
-rw-r--r--templates/firewall/modify/node.tag/rule/node.tag/log/node.def4
-rw-r--r--templates/firewall/name/node.tag/rule/node.tag/log/node.def4
-rw-r--r--templates/firewall/state-policy/established/action/node.def12
-rw-r--r--templates/firewall/state-policy/established/log/enable/node.def1
-rw-r--r--templates/firewall/state-policy/established/log/node.def1
-rw-r--r--templates/firewall/state-policy/established/node.def1
-rw-r--r--templates/firewall/state-policy/invalid/action/node.def12
-rw-r--r--templates/firewall/state-policy/invalid/log/enable/node.def1
-rw-r--r--templates/firewall/state-policy/invalid/log/node.def1
-rw-r--r--templates/firewall/state-policy/invalid/node.def1
-rw-r--r--templates/firewall/state-policy/node.def30
-rw-r--r--templates/firewall/state-policy/related/action/node.def12
-rw-r--r--templates/firewall/state-policy/related/log/enable/node.def1
-rw-r--r--templates/firewall/state-policy/related/log/node.def1
-rw-r--r--templates/firewall/state-policy/related/node.def1
22 files changed, 567 insertions, 24 deletions
diff --git a/Makefile.am b/Makefile.am
index bd8d923..f9f9466 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,6 +11,7 @@ curver_DATA = cfg-version/firewall@5
sbin_SCRIPTS += scripts/firewall/vyatta-firewall.pl
sbin_SCRIPTS += scripts/firewall/firewall.init
sbin_SCRIPTS += scripts/firewall/vyatta-ipset.pl
+sbin_SCRIPTS += scripts/firewall/vyatta-fw-global-state-policy.pl
share_perl5_DATA = lib/Vyatta/IpTables/Rule.pm
share_perl5_DATA += lib/Vyatta/IpTables/AddressFilter.pm
diff --git a/lib/Vyatta/IpTables/Mgr.pm b/lib/Vyatta/IpTables/Mgr.pm
index d14d9c5..b7c7a09 100755
--- a/lib/Vyatta/IpTables/Mgr.pm
+++ b/lib/Vyatta/IpTables/Mgr.pm
@@ -30,10 +30,124 @@ use warnings;
use base 'Exporter';
our @EXPORT = qw(ipt_find_chain_rule ipt_enable_conntrack
ipt_disable_conntrack count_iptables_rules
- chain_referenced ipt_get_queue_target);
+ chain_referenced ipt_get_queue_target
+ run_ipt_cmd create_ipt_chain delete_ipt_chain
+ flush_ipt_chain insert_ipt_rule append_ipt_rule
+ delete_ipt_rule delete_ipt_rulenum ipt_find_comment_rule);
-my $debug = 0;
+## TODO - in future, we could use perl's libiptc module instead of
+## running system commands in the following function for iptables.
+## However, that would need integrating the libiptc module into the system
+## and also adding other functionality to it, including IPv6 support.
+sub run_ipt_cmd {
+ my ($cmd) = shift;
+ my $error = system("$cmd");
+ my $debug = "false";
+ my $syslog = "false";
+ my $logger = "sudo logger -t Vyatta::IPTables::Mgr -p local0.warn --";
+
+ if ($syslog eq "true") {
+ my $func = (caller(1))[3];
+ system("$logger [$func] [$cmd] = [$error]");
+ }
+ if ($debug eq "true") {
+ my $func = (caller(1))[3];
+ print "\n[$func] [$cmd] = [$error]";
+ }
+ return $error;
+}
+
+sub create_ipt_chain {
+ my ($ipt_cmd, $table, $chain) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -N $chain";
+ $error = run_ipt_cmd($cmd);
+ return "create_ipt_chain [$ipt_cmd -t $table -N $chain]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+sub flush_ipt_chain {
+ my ($ipt_cmd, $table, $chain) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -F $chain";
+ $error = run_ipt_cmd($cmd);
+ return "flush_ipt_chain [$ipt_cmd -t $table -F $chain]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+sub delete_ipt_chain {
+ my ($ipt_cmd, $table, $chain) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -X $chain";
+ $error = run_ipt_cmd($cmd);
+ return "delete_ipt_chain [$ipt_cmd -t $table -X $chain]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+sub insert_ipt_rule {
+ my ($ipt_cmd, $table, $chain, $jump_target, $insert_num, $append_options) = @_;
+ my ($cmd, $error);
+
+ $insert_num = 1 if (!defined $insert_num);
+ $cmd = "sudo $ipt_cmd -t $table -I $chain $insert_num -j $jump_target ";
+ $cmd .= $append_options if defined $append_options;
+ $error = run_ipt_cmd($cmd);
+ return "insert_ipt_rule [$ipt_cmd -t $table -I $chain $insert_num -j $jump_target]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+sub append_ipt_rule {
+ my ($ipt_cmd, $table, $chain, $jump_target, $append_options) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -A $chain -j $jump_target ";
+ $cmd .= $append_options if defined $append_options;
+ $error = run_ipt_cmd($cmd);
+ return "append_ipt_rule [$ipt_cmd -t $table -A $chain -j $jump_target]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+# delete rule based on jump target. should only be used if jump_target is unique in that chain
+sub delete_ipt_rule {
+ my ($ipt_cmd, $table, $chain, $jump_target) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -D $chain -j $jump_target";
+ $error = run_ipt_cmd($cmd);
+ return "delete_ipt_rule [$ipt_cmd -t $table -D $chain -j $jump_target]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+# delete rule based on rule number
+sub delete_ipt_rulenum {
+ my ($ipt_cmd, $table, $chain, $delete_num) = @_;
+ my ($cmd, $error);
+
+ $cmd = "sudo $ipt_cmd -t $table -D $chain $delete_num";
+ $error = run_ipt_cmd($cmd);
+ return "delete_ipt_rulenum [$ipt_cmd -t $table -D $chain $delete_num]
+failed: [error code - $error]" if $error;
+
+ return;
+}
+
+# searches and returns first found rule based on jump target
sub ipt_find_chain_rule {
my ($iptables_cmd, $table, $chain, $search) = @_;
@@ -53,6 +167,29 @@ sub ipt_find_chain_rule {
return;
}
+# searches and returns first found rule based on matching text in rule comment
+sub ipt_find_comment_rule {
+ my ($iptables_cmd, $table, $chain, $search) = @_;
+
+ my $cmd = "$iptables_cmd -t $table -L $chain -vn --line";
+ my @lines = `sudo $cmd 2> /dev/null | egrep ^[0-9]`;
+ if (scalar(@lines) < 1) {
+ return;
+ }
+
+ my ($num, $rule_txt, $comment) = (undef, undef);
+ foreach my $line (@lines) {
+ ($rule_txt, $comment) = split /\/\*/, $line;
+ #print "rule_txt : $rule_txt, comment : $comment\n";
+ if (defined $comment && $comment =~ m/$search/) {
+ #print "found $search in $comment \n";
+ ($num) = split /\s+/, $rule_txt if defined $rule_txt;
+ return $num;
+ }
+ ($rule_txt, $comment) = (undef, undef);
+ }
+ return;
+}
my %conntrack_hook_hash =
('PREROUTING' => 'VYATTA_CT_PREROUTING_HOOK',
'OUTPUT' => 'VYATTA_CT_OUTPUT_HOOK',
@@ -87,6 +224,7 @@ sub ipt_enable_conntrack {
sub ipt_disable_conntrack {
my ($iptables_cmd, $chain) = @_;
+ my $debug = 0;
my @lines;
foreach my $label ('PREROUTING', 'OUTPUT') {
my $index;
diff --git a/scripts/firewall/firewall.init.in b/scripts/firewall/firewall.init.in
index 403dfc8..07c32f8 100644
--- a/scripts/firewall/firewall.init.in
+++ b/scripts/firewall/firewall.init.in
@@ -60,6 +60,29 @@ start () {
iptables -t raw -A OUTPUT -j VYATTA_CT_OUTPUT_HOOK
iptables -t raw -A OUTPUT -j NOTRACK
+ # set up pre-firewall hooks for IPv4
+ iptables -N VYATTA_PRE_FW_IN_HOOK
+ iptables -N VYATTA_PRE_FW_FWD_HOOK
+ iptables -N VYATTA_PRE_FW_OUT_HOOK
+ iptables -A VYATTA_PRE_FW_IN_HOOK -j RETURN
+ iptables -A VYATTA_PRE_FW_FWD_HOOK -j RETURN
+ iptables -A VYATTA_PRE_FW_OUT_HOOK -j RETURN
+ iptables -I INPUT -j VYATTA_PRE_FW_IN_HOOK
+ iptables -I FORWARD -j VYATTA_PRE_FW_FWD_HOOK
+ iptables -I OUTPUT -j VYATTA_PRE_FW_OUT_HOOK
+
+ # set up post-firewall hooks for IPv4
+ iptables -N VYATTA_POST_FW_IN_HOOK
+ iptables -N VYATTA_POST_FW_FWD_HOOK
+ iptables -N VYATTA_POST_FW_OUT_HOOK
+ iptables -A VYATTA_POST_FW_IN_HOOK -j ACCEPT
+ iptables -A VYATTA_POST_FW_FWD_HOOK -j ACCEPT
+ iptables -A VYATTA_POST_FW_OUT_HOOK -j ACCEPT
+ iptables -A INPUT -j VYATTA_POST_FW_IN_HOOK
+ iptables -A FORWARD -j VYATTA_POST_FW_FWD_HOOK
+ iptables -A OUTPUT -j VYATTA_POST_FW_OUT_HOOK
+
+ # set up IPV6 notrack and pre, post fw rules
if [ -d /proc/sys/net/ipv6 ] ; then
# set up notrack chains/rules for IPv6
ip6tables -t raw -N VYATTA_CT_PREROUTING_HOOK
@@ -71,6 +94,17 @@ start () {
ip6tables -t raw -A OUTPUT -j VYATTA_CT_OUTPUT_HOOK
ip6tables -t raw -A OUTPUT -j NOTRACK
+ # set up pre-firewall hooks for IPv6
+ ip6tables -N VYATTA_PRE_FW_IN_HOOK
+ ip6tables -N VYATTA_PRE_FW_FWD_HOOK
+ ip6tables -N VYATTA_PRE_FW_OUT_HOOK
+ ip6tables -A VYATTA_PRE_FW_IN_HOOK -j RETURN
+ ip6tables -A VYATTA_PRE_FW_FWD_HOOK -j RETURN
+ ip6tables -A VYATTA_PRE_FW_OUT_HOOK -j RETURN
+ ip6tables -I INPUT -j VYATTA_PRE_FW_IN_HOOK
+ ip6tables -I FORWARD -j VYATTA_PRE_FW_FWD_HOOK
+ ip6tables -I OUTPUT -j VYATTA_PRE_FW_OUT_HOOK
+
# set up post-firewall hooks for IPv6
ip6tables -N VYATTA_POST_FW_IN_HOOK
ip6tables -N VYATTA_POST_FW_FWD_HOOK
@@ -85,17 +119,6 @@ start () {
logger -t "Vyatta firewall init" -p warning "Kernel IPv6 support disabled. Not initializing IPv6 firewall"
fi
- # set up post-firewall hooks for IPv4
- iptables -N VYATTA_POST_FW_IN_HOOK
- iptables -N VYATTA_POST_FW_FWD_HOOK
- iptables -N VYATTA_POST_FW_OUT_HOOK
- iptables -A VYATTA_POST_FW_IN_HOOK -j ACCEPT
- iptables -A VYATTA_POST_FW_FWD_HOOK -j ACCEPT
- iptables -A VYATTA_POST_FW_OUT_HOOK -j ACCEPT
- iptables -A INPUT -j VYATTA_POST_FW_IN_HOOK
- iptables -A FORWARD -j VYATTA_POST_FW_FWD_HOOK
- iptables -A OUTPUT -j VYATTA_POST_FW_OUT_HOOK
-
# set up pre-DNAT hook
iptables -t nat -N VYATTA_PRE_DNAT_HOOK
iptables -t nat -A VYATTA_PRE_DNAT_HOOK -j RETURN
diff --git a/scripts/firewall/vyatta-firewall.pl b/scripts/firewall/vyatta-firewall.pl
index d3ac47e..ae9f723 100755
--- a/scripts/firewall/vyatta-firewall.pl
+++ b/scripts/firewall/vyatta-firewall.pl
@@ -719,15 +719,17 @@ sub setup_iptables {
# add VYATTA_FW_(IN|OUT)_HOOK
my $num = find_chain_rule($iptables_cmd, $table, $ohook, $FW_OUT_HOOK);
if (! defined $num) {
+ my $insert_at = 1;
+ $insert_at = 2 if ($table eq 'filter'); # insert after VYATTA_PRE_FW_*_HOOK
run_cmd("$iptables_cmd -t $table -N $FW_OUT_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $ohook 1 -j $FW_OUT_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $ohook $insert_at -j $FW_OUT_HOOK", 1);
run_cmd("$iptables_cmd -t $table -N $FW_IN_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $ihook 1 -j $FW_IN_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $ihook $insert_at -j $FW_IN_HOOK", 1);
# add VYATTA_FW_LOCAL_HOOK only in filter table
if ($table eq 'filter') {
my $lhook = $localhook_hash{$table};
run_cmd("$iptables_cmd -t $table -N $FW_LOCAL_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $lhook 1 -j $FW_LOCAL_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $lhook $insert_at -j $FW_LOCAL_HOOK", 1);
}
}
diff --git a/scripts/firewall/vyatta-fw-global-state-policy.pl b/scripts/firewall/vyatta-fw-global-state-policy.pl
new file mode 100755
index 0000000..526c1a1
--- /dev/null
+++ b/scripts/firewall/vyatta-fw-global-state-policy.pl
@@ -0,0 +1,304 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-fw-global-state-policy.pl
+#
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2011 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Mohit Mehta
+# Date: November 2011
+# Description: Script for setting/changing/removing global FW state-policy
+#
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5";
+use warnings;
+use strict;
+use Switch;
+use Vyatta::Config;
+use Vyatta::IpTables::Mgr;
+use Getopt::Long;
+use Sys::Syslog qw(:standard :macros);
+
+# mapping from config node to iptables command
+our %cmd_hash = ( 'name' => '/sbin/iptables',
+ 'ipv6-name' => '/sbin/ip6tables');
+
+# mapping from config node to iptables/ip6tables table
+our %table_hash = ( 'name' => 'filter',
+ 'ipv6-name' => 'filter');
+
+# pre FW hooks in iptables' INPUT, OUTPUT and FORWARD chains
+our %pre_fw_hooks_hash = ( 'INPUT' => 'VYATTA_PRE_FW_IN_HOOK',
+ 'FORWARD' => 'VYATTA_PRE_FW_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_PRE_FW_OUT_HOOK');
+
+# post FW hooks in iptables' INPUT, OUTPUT and FORWARD chains
+our %post_fw_hooks_hash = ( 'INPUT' => 'VYATTA_POST_FW_IN_HOOK',
+ 'FORWARD' => 'VYATTA_POST_FW_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_POST_FW_OUT_HOOK');
+
+# state policy chains in iptables' INPUT, OUTPUT and FORWARD chains
+our %state_policy_chains_hash = ( 'INPUT' => 'VYATTA_STATE_POLICY_IN_HOOK',
+ 'FORWARD' => 'VYATTA_STATE_POLICY_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_STATE_POLICY_OUT_HOOK');
+
+# state actions
+our %state_action_hash = ( 'drop' => 'DROP',
+ 'reject' => 'REJECT',
+ 'accept' => 'JUMP_TO_INDIVIDUAL_POST_FW_HOOK',
+ 'log' => 'LOG');
+
+# state actions' log abbreviations
+our %state_log_abbr_hash = ( 'drop' => 'D',
+ 'reject' => 'R',
+ 'accept' => 'A');
+
+# imp to maintain order of this array since this is the
+# order we want to insert rules into state-policy chains
+my @fw_states = ('invalid', 'established', 'related');
+
+# log prefix - FW_STATE_POL-$STATE-$ACTION_ABBREVIATION
+my $fw_log_prefix = 'FW-STATE_POL';
+
+# this function performs the following functions:
+# 1. sets up VYATTA_FW_*_STATE_POLICY chains i.e. for INPUT, OUTPUT, FORWARD hooks
+# 2. adds rules in VYATTA_PRE_FW_*_HOOK hooks to jump to VYATTA_FW_*_STATE_POLICY
+sub setup_state_policy {
+ my ($cmd, $error);
+
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # create VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::create_ipt_chain ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # append RETURN to VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, 'RETURN');
+ return ($error, ) if $error;
+
+ # insert rule in VYATTA_PRE_FW_*_HOOK to jump to VYATTA_FW_*_STATE_POLICY
+ $error = Vyatta::IpTables::Mgr::insert_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $pre_fw_hooks_hash{$iptables_chain},
+$state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+# this function reverts the operations done in setup_state_policy():
+# 1. removes rules from VYATTA_PRE_FW_*_HOOK hooks to jump to VYATTA_FW_*_STATE_POLICY
+# 2. deletes VYATTA_FW_STATE_POLICY chains i.e. for IN, OUT, FWD hooks
+sub teardown_state_policy {
+ my ($cmd, $error);
+
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # remove rule in VYATTA_PRE_FW_*_HOOK to jump to VYATTA_FW_*_STATE_POLICY
+ $error = Vyatta::IpTables::Mgr::delete_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $pre_fw_hooks_hash{$iptables_chain},
+$state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # flush all rules from VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::flush_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # delete VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::delete_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+# set all state actions and their log rules
+# Flush all previous rules and then set rules in the following order:
+# INVALID - log rule followed by action rule
+# ESTABLISHED - log rule followed by action rule
+# RELATED - log rule followed by action rule
+# Keep appending rules and then append RETURN rule at the end
+sub set_state_actions {
+ my ($cmd, $error);
+
+ my $config = new Vyatta::Config;
+ # skip steps below if state-policy deleted
+ return if (!defined $config->exists("firewall state-policy"));
+
+ # flush state_policy_chains
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # flush all rules from VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::flush_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ # check config for each states in this order: invalid, established, related
+ # insert rules for log and action for each state
+ foreach my $state (@fw_states) {
+ $config->setLevel("firewall state-policy $state");
+ my ($action, $log_enabled) = (undef, undef);
+ $log_enabled = $config->exists("log enable");
+ $action = $config->returnValue("action");
+ my $uc_action = uc($action) if defined $action;
+ my $uc_state = uc ($state) if defined $state;
+ if (defined $log_enabled) {
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # insert rule in VYATTA_FW_*_STATE_POLICY
+ my $jump_target = "LOG --log-prefix \"[$fw_log_prefix-$uc_state-$state_log_abbr_hash{$action}]\" ";
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, $jump_target, "-m state --state $uc_state");
+ return ($error, ) if $error;
+ }
+ }
+ }
+ if (defined $action) {
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # if action is accept then jump target shold be post_fw_hooks post_fw_hooks_hash
+ if ($action eq 'accept') {
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain},
+$post_fw_hooks_hash{$iptables_chain}, "-m state --state $uc_state");
+ } else {
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain},
+$uc_action, "-m state --state $uc_state");
+ }
+ return ($error, ) if $error;
+ }
+ }
+ }
+ }
+
+ # append rule with target RETURN at the end
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # append RETURN to VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, 'RETURN');
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+sub enable_disable_conntrack {
+ my ($cmd, $error);
+
+ my $conntrack_enabled = 'false';
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action) = (undef);
+ $action = $config->returnOrigValue("action");
+ if (defined $action) {
+ $conntrack_enabled = 'true';
+ last;
+ }
+ }
+ if ($conntrack_enabled eq 'true') {
+ foreach my $tree (keys %cmd_hash) {
+ Vyatta::IpTables::Mgr::ipt_disable_conntrack($cmd_hash{$tree}, 'FW_STATE_POLICY_CONNTRACK');
+ }
+ }
+
+ my $enable_conntrack = 'false';
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action) = (undef);
+ $action = $config->returnValue("action");
+ if (defined $action) {
+ $enable_conntrack = 'true';
+ last;
+ }
+ }
+ if ($enable_conntrack eq 'true') {
+ foreach my $tree (keys %cmd_hash) {
+ Vyatta::IpTables::Mgr::ipt_enable_conntrack($cmd_hash{$tree}, 'FW_STATE_POLICY_CONNTRACK');
+ }
+ }
+
+ return;
+}
+
+sub state_policy_validity_checks {
+ my ($cmd, $error);
+
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action, $log_enabled) = (undef, undef);
+ $log_enabled = $config->exists("log enable");
+ $action = $config->returnValue("action");
+ if (defined $log_enabled && !defined $action) {
+ $error = "log enabled but action not configured for state: $state\n" .
+"action is required to log packets\n";
+ return $error;
+ }
+ }
+
+ return;
+}
+
+#
+# main
+#
+
+my ($action, $state, $state_action);
+
+GetOptions("action=s" => \$action,
+ "state=s" => \$state,
+ "state-action=s" => \$state_action,
+);
+
+die "undefined action" if ! defined $action;
+
+my ($error, $warning);
+
+($error, $warning) = setup_state_policy() if $action eq 'setup-state-policy';
+
+($error, $warning) = teardown_state_policy() if $action eq 'teardown-state-policy';
+
+($error, $warning) = set_state_actions() if $action eq 'set-state-actions';
+
+($error, $warning) = enable_disable_conntrack($state) if $action eq 'enable-disable-conntrack';
+
+($error, $warning) = state_policy_validity_checks($state) if $action eq 'state-policy-validity-checks';
+
+if (defined $warning) {
+ print "$warning\n";
+}
+
+if (defined $error) {
+ print "$error\n";
+ exit 1;
+}
+
+exit 0;
+
+# end of file
diff --git a/templates/firewall/ipv6-modify/node.tag/rule/node.tag/log/node.def b/templates/firewall/ipv6-modify/node.tag/rule/node.tag/log/node.def
index ba0e74b..891cbcf 100644
--- a/templates/firewall/ipv6-modify/node.tag/rule/node.tag/log/node.def
+++ b/templates/firewall/ipv6-modify/node.tag/rule/node.tag/log/node.def
@@ -1,3 +1,3 @@
-type: txt; "firwall logging must be enable or disable"
+type: txt; "firewall logging must be enable or disable"
help: Option to log packets matching rule
-syntax:expression: $VAR(@) in "enable", "disable"; "firwall logging must be enable or disable"
+syntax:expression: $VAR(@) in "enable", "disable"; "firewall logging must be enable or disable"
diff --git a/templates/firewall/ipv6-name/node.tag/rule/node.tag/log/node.def b/templates/firewall/ipv6-name/node.tag/rule/node.tag/log/node.def
index ba0e74b..891cbcf 100644
--- a/templates/firewall/ipv6-name/node.tag/rule/node.tag/log/node.def
+++ b/templates/firewall/ipv6-name/node.tag/rule/node.tag/log/node.def
@@ -1,3 +1,3 @@
-type: txt; "firwall logging must be enable or disable"
+type: txt; "firewall logging must be enable or disable"
help: Option to log packets matching rule
-syntax:expression: $VAR(@) in "enable", "disable"; "firwall logging must be enable or disable"
+syntax:expression: $VAR(@) in "enable", "disable"; "firewall logging must be enable or disable"
diff --git a/templates/firewall/modify/node.tag/rule/node.tag/log/node.def b/templates/firewall/modify/node.tag/rule/node.tag/log/node.def
index ba0e74b..891cbcf 100644
--- a/templates/firewall/modify/node.tag/rule/node.tag/log/node.def
+++ b/templates/firewall/modify/node.tag/rule/node.tag/log/node.def
@@ -1,3 +1,3 @@
-type: txt; "firwall logging must be enable or disable"
+type: txt; "firewall logging must be enable or disable"
help: Option to log packets matching rule
-syntax:expression: $VAR(@) in "enable", "disable"; "firwall logging must be enable or disable"
+syntax:expression: $VAR(@) in "enable", "disable"; "firewall logging must be enable or disable"
diff --git a/templates/firewall/name/node.tag/rule/node.tag/log/node.def b/templates/firewall/name/node.tag/rule/node.tag/log/node.def
index ba0e74b..891cbcf 100644
--- a/templates/firewall/name/node.tag/rule/node.tag/log/node.def
+++ b/templates/firewall/name/node.tag/rule/node.tag/log/node.def
@@ -1,3 +1,3 @@
-type: txt; "firwall logging must be enable or disable"
+type: txt; "firewall logging must be enable or disable"
help: Option to log packets matching rule
-syntax:expression: $VAR(@) in "enable", "disable"; "firwall logging must be enable or disable"
+syntax:expression: $VAR(@) in "enable", "disable"; "firewall logging must be enable or disable"
diff --git a/templates/firewall/state-policy/established/action/node.def b/templates/firewall/state-policy/established/action/node.def
new file mode 100644
index 0000000..136814f
--- /dev/null
+++ b/templates/firewall/state-policy/established/action/node.def
@@ -0,0 +1,12 @@
+type: txt
+
+help: Action for packets part of an established connection
+
+syntax:expression: $VAR(@) in "accept", "drop", "reject";
+ "action must be one of accept, drop, or reject"
+
+allowed: echo "accept drop reject"
+
+val_help: accept ; Action to accept
+val_help: drop ; Action to drop
+val_help: reject ; Action to reject
diff --git a/templates/firewall/state-policy/established/log/enable/node.def b/templates/firewall/state-policy/established/log/enable/node.def
new file mode 100644
index 0000000..406ca0d
--- /dev/null
+++ b/templates/firewall/state-policy/established/log/enable/node.def
@@ -0,0 +1 @@
+help: Enable logging of packets part of an established connection
diff --git a/templates/firewall/state-policy/established/log/node.def b/templates/firewall/state-policy/established/log/node.def
new file mode 100644
index 0000000..78125ae
--- /dev/null
+++ b/templates/firewall/state-policy/established/log/node.def
@@ -0,0 +1 @@
+help: Option to log packets part of an established connection
diff --git a/templates/firewall/state-policy/established/node.def b/templates/firewall/state-policy/established/node.def
new file mode 100644
index 0000000..8a199e2
--- /dev/null
+++ b/templates/firewall/state-policy/established/node.def
@@ -0,0 +1 @@
+help: Global firewall policy for packets part of an established connection
diff --git a/templates/firewall/state-policy/invalid/action/node.def b/templates/firewall/state-policy/invalid/action/node.def
new file mode 100644
index 0000000..1d5b12f
--- /dev/null
+++ b/templates/firewall/state-policy/invalid/action/node.def
@@ -0,0 +1,12 @@
+type: txt
+
+help: Action for packets part of an invalid connection
+
+syntax:expression: $VAR(@) in "accept", "drop", "reject";
+ "action must be one of accept, drop, or reject"
+
+allowed: echo "accept drop reject"
+
+val_help: accept ; Action to accept
+val_help: drop ; Action to drop
+val_help: reject ; Action to reject
diff --git a/templates/firewall/state-policy/invalid/log/enable/node.def b/templates/firewall/state-policy/invalid/log/enable/node.def
new file mode 100644
index 0000000..29e0907
--- /dev/null
+++ b/templates/firewall/state-policy/invalid/log/enable/node.def
@@ -0,0 +1 @@
+help: Enable logging of packets part of an invalid connection
diff --git a/templates/firewall/state-policy/invalid/log/node.def b/templates/firewall/state-policy/invalid/log/node.def
new file mode 100644
index 0000000..cfd56b3
--- /dev/null
+++ b/templates/firewall/state-policy/invalid/log/node.def
@@ -0,0 +1 @@
+help: Option to log packets part of an invalid connection
diff --git a/templates/firewall/state-policy/invalid/node.def b/templates/firewall/state-policy/invalid/node.def
new file mode 100644
index 0000000..71bbf20
--- /dev/null
+++ b/templates/firewall/state-policy/invalid/node.def
@@ -0,0 +1 @@
+help: Global firewall policy for packets part of an invalid connection
diff --git a/templates/firewall/state-policy/node.def b/templates/firewall/state-policy/node.def
new file mode 100644
index 0000000..a745c31
--- /dev/null
+++ b/templates/firewall/state-policy/node.def
@@ -0,0 +1,30 @@
+priority: 200
+help: Global firewall state-policy
+
+begin:
+ if ! /opt/vyatta/sbin/vyatta-fw-global-state-policy.pl \
+ --action=state-policy-validity-checks; then \
+ exit 1
+ fi
+
+create:
+ if ! /opt/vyatta/sbin/vyatta-fw-global-state-policy.pl \
+ --action=setup-state-policy; then \
+ exit 1
+ fi
+
+delete:
+ if ! /opt/vyatta/sbin/vyatta-fw-global-state-policy.pl \
+ --action=teardown-state-policy; then \
+ exit 1
+ fi
+
+end:
+ if ! /opt/vyatta/sbin/vyatta-fw-global-state-policy.pl \
+ --action=set-state-actions; then \
+ exit 1
+ fi
+ if ! /opt/vyatta/sbin/vyatta-fw-global-state-policy.pl \
+ --action=enable-disable-conntrack; then \
+ exit 1
+ fi
diff --git a/templates/firewall/state-policy/related/action/node.def b/templates/firewall/state-policy/related/action/node.def
new file mode 100644
index 0000000..d14a09b
--- /dev/null
+++ b/templates/firewall/state-policy/related/action/node.def
@@ -0,0 +1,12 @@
+type: txt
+
+help: Action for packets part of a related connection
+
+syntax:expression: $VAR(@) in "accept", "drop", "reject";
+ "action must be one of accept, drop, or reject"
+
+allowed: echo "accept drop reject"
+
+val_help: accept ; Action to accept
+val_help: drop ; Action to drop
+val_help: reject ; Action to reject
diff --git a/templates/firewall/state-policy/related/log/enable/node.def b/templates/firewall/state-policy/related/log/enable/node.def
new file mode 100644
index 0000000..8f64b77
--- /dev/null
+++ b/templates/firewall/state-policy/related/log/enable/node.def
@@ -0,0 +1 @@
+help: Enable logging of packets part of a related connection
diff --git a/templates/firewall/state-policy/related/log/node.def b/templates/firewall/state-policy/related/log/node.def
new file mode 100644
index 0000000..245928b
--- /dev/null
+++ b/templates/firewall/state-policy/related/log/node.def
@@ -0,0 +1 @@
+help: Option to log packets part of a related connection
diff --git a/templates/firewall/state-policy/related/node.def b/templates/firewall/state-policy/related/node.def
new file mode 100644
index 0000000..78125ae
--- /dev/null
+++ b/templates/firewall/state-policy/related/node.def
@@ -0,0 +1 @@
+help: Option to log packets part of an established connection