summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlib/Vyatta/IpTables/IpSet.pm37
-rwxr-xr-xscripts/firewall/vyatta-ipset.pl72
-rw-r--r--templates/firewall/group/address-group/node.def11
-rw-r--r--templates/firewall/group/address-group/node.tag/address/node.def93
-rw-r--r--templates/firewall/group/network-group/node.def10
-rw-r--r--templates/firewall/group/network-group/node.tag/network/node.def18
-rw-r--r--templates/firewall/group/port-group/node.def11
-rw-r--r--templates/firewall/group/port-group/node.tag/port/node.def87
-rw-r--r--templates/firewall/modify/node.def1
-rw-r--r--templates/firewall/name/node.def1
-rw-r--r--templates/firewall/node.def2
11 files changed, 100 insertions, 243 deletions
diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm
index 703a3ac..607333c 100755
--- a/lib/Vyatta/IpTables/IpSet.pm
+++ b/lib/Vyatta/IpTables/IpSet.pm
@@ -40,7 +40,7 @@ my %fields = (
_debug => undef,
);
-my %grouptype_hash = (
+our %grouptype_hash = (
'address' => 'hash:ip',
'network' => 'hash:net',
'port' => 'bitmap:port'
@@ -175,8 +175,8 @@ sub create {
return "Error: undefined group name" if ! defined $self->{_name};
return "Error: undefined group type" if ! defined $self->{_type};
- return "Error: group [$self->{_name}] already exists" if $self->exists();
-
+ return if $self->exists(); # treat as nop if already exists
+
my $ipset_param = $grouptype_hash{$self->{_type}};
return "Error: invalid group type\n" if ! defined $ipset_param;
@@ -203,6 +203,14 @@ sub references {
return 0;
}
+sub flush {
+ my ($self) = @_;
+ my $cmd = "ipset flush $self->{_name}";
+ my $rc = $self->run_cmd($cmd);
+ return "Error: call to ipset failed [$rc]" if $rc;
+ return;
+}
+
sub delete {
my ($self) = @_;
@@ -210,7 +218,15 @@ sub delete {
return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists();
my $refs = $self->references();
- return "Error: group [$self->{_name}] still in use.\n" if $refs != 0;
+ if ($refs > 0) {
+ # still in use
+ if (scalar($self->get_firewall_references(1)) > 0) {
+ # still referenced by config
+ return "Error: group [$self->{_name}] still in use.\n";
+ }
+ # not referenced by config => simultaneous deletes. just do flush.
+ return $self->flush();
+ }
my $cmd = "ipset -X $self->{_name}";
my $rc = $self->run_cmd($cmd);
@@ -391,25 +407,28 @@ sub get_description {
}
sub get_firewall_references {
- my ($self) = @_;
-
+ my ($self, $working) = @_;
+ my ($lfunc, $vfunc) = qw(listOrigNodes returnOrigValue);
+ if ($working) {
+ ($lfunc, $vfunc) = qw(listNodes returnValue);
+ }
my @fw_refs = ();
return @fw_refs if ! $self->exists();
my $config = new Vyatta::Config;
foreach my $tree ('name', 'modify') {
my $path = "firewall $tree ";
$config->setLevel($path);
- my @names = $config->listOrigNodes();
+ my @names = $config->$lfunc();
foreach my $name (@names) {
my $name_path = "$path $name rule ";
$config->setLevel($name_path);
- my @rules = $config->listOrigNodes();
+ my @rules = $config->$lfunc();
foreach my $rule (@rules) {
foreach my $dir ('source', 'destination') {
my $rule_path = "$name_path $rule $dir group";
$config->setLevel($rule_path);
my $group_type = "$self->{_type}-group";
- my $value = $config->returnOrigValue($group_type);
+ my $value = $config->$vfunc($group_type);
$value =~ s/^!(.*)$/$1/ if defined $value;
if (defined $value and $self->{_name} eq $value) {
push @fw_refs, "$name-$rule-$dir";
diff --git a/scripts/firewall/vyatta-ipset.pl b/scripts/firewall/vyatta-ipset.pl
index 18bd270..7ee7bdc 100755
--- a/scripts/firewall/vyatta-ipset.pl
+++ b/scripts/firewall/vyatta-ipset.pl
@@ -31,6 +31,7 @@ use Vyatta::Config;
use Vyatta::TypeChecker;
use Vyatta::Misc;
use Vyatta::IpTables::IpSet;
+use Sort::Versions;
use warnings;
use strict;
@@ -82,13 +83,9 @@ sub ipset_check_set_type {
die "Error: undefined set_name\n" if ! defined $set_name;
die "Error: undefined set_type\n" if ! defined $set_type;
- my $group = new Vyatta::IpTables::IpSet($set_name);
- return "Group [$set_name] has not been defined\n" if ! $group->exists();
- my $type = $group->get_type();
- $type = 'undefined' if ! defined $type;
- if ($type ne $set_type) {
- return "Error: group [$set_name] is of type [$type] not [$set_type]\n";
- }
+ my $cfg = new Vyatta::Config;
+ return "Group [$set_name] has not been defined\n"
+ if (!$cfg->exists("firewall group $set_type-group $set_name"));
return;
}
@@ -127,12 +124,16 @@ sub ipset_is_set_empty {
sub ipset_show_sets {
my @lines = `ipset -L`;
+ my @sets = ();
foreach my $line (@lines) {
if ($line =~ /^Name:\s+(\S+)$/ ) {
- ipset_show_members($1);
- print "\n";
+ push @sets, $1;
}
}
+ foreach my $set (sort { versioncmp($b, $a) } (@sets)) {
+ ipset_show_members($set);
+ print "\n";
+ }
return;
}
@@ -199,6 +200,56 @@ sub ipset_is_group_used {
exit 1;
}
+sub update_set {
+ my ($set_name, $set_type) = @_;
+ my $cfg = new Vyatta::Config;
+ my $rc;
+ my $cpath = "firewall group $set_type-group $set_name";
+ if ($cfg->existsOrig($cpath)) {
+ if (!$cfg->exists($cpath)) {
+ # deleted
+ return $rc if (($rc = ipset_delete($set_name)));
+ return;
+ }
+ } else {
+ if ($cfg->exists($cpath)) {
+ # added
+ return $rc if (($rc = ipset_create($set_name, $set_type)));
+ } else {
+ # doesn't exist! should not happen
+ return "Updating non-existent group [$set_name]";
+ }
+
+ }
+ # added or potentially changed => iterate members
+ my @ovals = $cfg->returnOrigValues("$cpath $set_type");
+ my @nvals = $cfg->returnValues("$cpath $set_type");
+ my %vals = $cfg->compareValueLists(\@ovals, \@nvals);
+ for my $d (@{$vals{deleted}}) {
+ return $rc if (($rc = ipset_delete_member($set_name, $d)));
+ }
+ for my $a (@{$vals{added}}) {
+ return $rc if (($rc = ipset_add_member($set_name, $a)));
+ }
+ exit 0;
+}
+
+sub prune_deleted_sets {
+ my $cfg = new Vyatta::Config;
+ my @set_types = keys(%Vyatta::IpTables::IpSet::grouptype_hash);
+ foreach my $set_type (@set_types) {
+ $cfg->setLevel("firewall group $set_type-group");
+ my %groups = $cfg->listNodeStatus();
+ next if (scalar(keys(%groups)) < 1);
+ foreach my $g (keys(%groups)) {
+ next if ($groups{$g} ne 'deleted');
+ next if ($cfg->isEffective($g)); # don't prune if delete failed
+ my $rc;
+ return $rc if (($rc = ipset_delete($g)));
+ }
+ }
+ exit 0;
+}
#
# main
@@ -242,6 +293,9 @@ $rc = ipset_is_group_deleted($set_name, $set_type)
$rc = ipset_is_group_used($set_name, $set_type) if $action eq 'is-group-used';
+$rc = update_set($set_name, $set_type) if $action eq 'update-set';
+$rc = prune_deleted_sets() if $action eq 'prune-deleted-sets';
+
if (defined $rc) {
print $rc;
exit 1;
diff --git a/templates/firewall/group/address-group/node.def b/templates/firewall/group/address-group/node.def
index 40462fa..5b2e510 100644
--- a/templates/firewall/group/address-group/node.def
+++ b/templates/firewall/group/address-group/node.def
@@ -15,12 +15,5 @@ syntax:expression: pattern $VAR(@) "^[^!]" ; \
syntax:expression: pattern $VAR(@) "^[^|;&$<>]*$" ; \
"Firewall group name cannot contain shell punctuation"
-create: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=create-set \
- --set-type=address \
- --set-name="$VAR(@)"
-
-
-delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=delete-set \
- --set-name="$VAR(@)"
+end: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=update-set \
+ --set-name="$VAR(@)" --set-type=address
diff --git a/templates/firewall/group/address-group/node.tag/address/node.def b/templates/firewall/group/address-group/node.tag/address/node.def
index a04dd5b..2629b9d 100644
--- a/templates/firewall/group/address-group/node.tag/address/node.def
+++ b/templates/firewall/group/address-group/node.tag/address/node.def
@@ -10,96 +10,3 @@ syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \
--set-type=address \
--member=\"$VAR(@)\"; "
-create: tmpgrp=$VAR(../@)-$PPID
- len=${#tmpgrp}
- if [ "$len" -gt 31 ]; then
- tmpgrp=${tmpgrp: -31};
- if [[ "$tmpgrp" =~ ^- ]]; then
- tmpgrp=${tmpgrp/-/Z};
- fi
- fi
- tmpfile="/tmp/$tmpgrp";
-
- # echo create $VAR(@) $tmpgrp $COMMIT_SIBLING_POSITION
-
- if [ "$COMMIT_SIBLING_POSITION" = "FIRST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-set-empty \
- --set-name=$VAR(../@)
- if [ $? != 0 ]; then
- # echo create $tmpfile;
- touch $tmpfile;
- fi;
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=copy-set \
- --set-name=$VAR(../@) --set-type=address --set-copy=$tmpgrp
- # echo create $tmpgrp
- fi;
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \
- --set-name="$tmpgrp" --member="$VAR(@)" --alias=$VAR(../@)
- if [ $? != 0 ]; then
- # echo error adding, destroy $tmpgrp
- sudo ipset --destroy $tmpgrp;
- if [ -e $tmpfile ]; then
- # echo destroy $VAR(../@)
- sudo ipset --destroy $VAR(../@);
- rm $tmpfile;
- fi;
- exit 1;
- fi;
-
- if [ "$COMMIT_SIBLING_POSITION" = "LAST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- # echo swap and destroy $tmpgrp
- sudo ipset --swap $tmpgrp "$VAR(../@)";
- sudo ipset --destroy $tmpgrp;
- rm -f $tmpfile;
- fi;
-
-delete: tmpgrp=$VAR(../@)-$PPID
- len=${#tmpgrp}
- if [ "$len" -gt 31 ]; then
- tmpgrp=${tmpgrp: -31};
- if [[ "$tmpgrp" =~ ^- ]]; then
- tmpgrp=${tmpgrp/-/Z};
- fi
- fi
- tmpfile="/tmp/$tmpgrp";
-
- # echo delete $VAR(@) $tmpgrp $COMMIT_SIBLING_POSITION
-
- if [ "$COMMIT_SIBLING_POSITION" = "FIRST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-set-empty \
- --set-name=$VAR(../@)
- if [ $? != 0 ]; then
- # echo create $tmpfile;
- touch $tmpfile;
- fi;
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=copy-set \
- --set-name=$VAR(../@) --set-type=address --set-copy=$tmpgrp
- # echo create $tmpgrp
- fi;
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-deleted \
- --set-name=$VAR(../@) --set-type=address;
- if [ $? == 0 ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-used \
- --set-name=$VAR(../@) --set-type=address
- if [ $? == 0 ] ; then
- echo "Error: group [$VAR(../@)] still in use."
- exit 1;
- fi
- fi
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \
- --set-name=$tmpgrp \
- --member="$VAR(@)"
-
- if [ "$COMMIT_SIBLING_POSITION" = "LAST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- # echo swap and destroy $tmpgrp
- sudo ipset --swap $tmpgrp "$VAR(../@)";
- sudo ipset --destroy $tmpgrp;
- rm -f $tmpfile;
- fi;
diff --git a/templates/firewall/group/network-group/node.def b/templates/firewall/group/network-group/node.def
index e20b536..8e50b7d 100644
--- a/templates/firewall/group/network-group/node.def
+++ b/templates/firewall/group/network-group/node.def
@@ -15,12 +15,6 @@ syntax:expression: pattern $VAR(@) "^[^!]" ; \
syntax:expression: pattern $VAR(@) "^[^|;&$<>]*$" ; \
"Firewall group name cannot contain shell punctuation"
-create: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=create-set \
- --set-type=network \
- --set-name="$VAR(@)"
+end: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=update-set \
+ --set-name="$VAR(@)" --set-type=network
-
-delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=delete-set \
- --set-name="$VAR(@)"
diff --git a/templates/firewall/group/network-group/node.tag/network/node.def b/templates/firewall/group/network-group/node.tag/network/node.def
index 4db4d49..7388561 100644
--- a/templates/firewall/group/network-group/node.tag/network/node.def
+++ b/templates/firewall/group/network-group/node.tag/network/node.def
@@ -12,21 +12,3 @@ syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \
syntax:expression: exec " \
/opt/vyatta/sbin/check_prefix_boundary $VAR(@)" \
-create: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \
- --set-name=$VAR(../@) \
- --member="$VAR(@)"
-
-delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-deleted \
- --set-name=$VAR(../@) --set-type=network;
- if [ $? == 0 ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-used \
- --set-name=$VAR(../@) --set-type=network
- if [ $? == 0 ] ; then
- echo "Error: group [$VAR(../@)] still in use."
- exit 1;
- fi
- fi
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \
- --set-name=$VAR(../@) \
- --member="$VAR(@)"
diff --git a/templates/firewall/group/port-group/node.def b/templates/firewall/group/port-group/node.def
index 76fef9e..949403e 100644
--- a/templates/firewall/group/port-group/node.def
+++ b/templates/firewall/group/port-group/node.def
@@ -15,12 +15,5 @@ syntax:expression: pattern $VAR(@) "^[^!]" ; \
syntax:expression: pattern $VAR(@) "^[^|;&$<>]*$" ; \
"Firewall group name cannot contain shell punctuation"
-create: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=create-set \
- --set-type=port \
- --set-name="$VAR(@)"
-
-
-delete: sudo /opt/vyatta/sbin/vyatta-ipset.pl \
- --action=delete-set \
- --set-name="$VAR(@)"
+end: sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=update-set \
+ --set-name="$VAR(@)" --set-type=port
diff --git a/templates/firewall/group/port-group/node.tag/port/node.def b/templates/firewall/group/port-group/node.tag/port/node.def
index 6e657c4..7a9b867 100644
--- a/templates/firewall/group/port-group/node.tag/port/node.def
+++ b/templates/firewall/group/port-group/node.tag/port/node.def
@@ -11,90 +11,3 @@ syntax:expression: exec "sudo /opt/vyatta/sbin/vyatta-ipset.pl \
--set-name=$VAR(../@) \
--set-type=port \
--member=\"$VAR(@)\"; "
-
-create: tmpgrp=$VAR(../@)-$PPID
- len=${#tmpgrp}
- if [ "$len" -gt 31 ]; then
- tmpgrp=${tmpgrp: -31};
- if [[ "$tmpgrp" =~ ^- ]]; then
- tmpgrp=${tmpgrp/-/Z};
- fi
- fi
- tmpfile="/tmp/$tmpgrp";
-
- if [ "$COMMIT_SIBLING_POSITION" = "FIRST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-set-empty \
- --set-name=$VAR(../@)
- if [ $? != 0 ]; then
- touch $tmpfile;
- fi;
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=copy-set \
- --set-name=$VAR(../@) --set-type=port --set-copy=$tmpgrp
- fi;
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=add-member \
- --set-name="$tmpgrp" --member="$VAR(@)" --alias=$VAR(../@)
- if [ $? != 0 ]; then
- sudo ipset --destroy $tmpgrp;
- if [ -e $tmpfile ]; then
- sudo ipset --destroy $VAR(../@);
- rm $tmpfile;
- fi;
- exit 1;
- fi;
-
- if [ "$COMMIT_SIBLING_POSITION" = "LAST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- sudo ipset --swap $tmpgrp "$VAR(../@)";
- sudo ipset --destroy $tmpgrp;
- rm -f $tmpfile;
- fi;
-
-delete: tmpgrp=$VAR(../@)-$PPID
- len=${#tmpgrp}
- if [ "$len" -gt 31 ]; then
- tmpgrp=${tmpgrp: -31};
- if [[ "$tmpgrp" =~ ^- ]]; then
- tmpgrp=${tmpgrp/-/Z};
- fi
- fi
- tmpfile="/tmp/$tmpgrp";
-
- # echo delete $VAR(@) $tmpgrp $COMMIT_SIBLING_POSITION
-
- if [ "$COMMIT_SIBLING_POSITION" = "FIRST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-set-empty \
- --set-name=$VAR(../@)
- if [ $? != 0 ]; then
- # echo create $tmpfile;
- touch $tmpfile;
- fi;
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=copy-set \
- --set-name=$VAR(../@) --set-type=port --set-copy=$tmpgrp
- # echo create $tmpgrp
- fi;
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-deleted \
- --set-name=$VAR(../@) --set-type=port;
- if [ $? == 0 ] ; then
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=is-group-used \
- --set-name=$VAR(../@) --set-type=port
- if [ $? == 0 ] ; then
- echo "Error: group [$VAR(../@)] still in use."
- exit 1;
- fi
- fi
-
- sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=delete-member \
- --set-name=$tmpgrp \
- --member="$VAR(@)"
-
- if [ "$COMMIT_SIBLING_POSITION" = "LAST" ] || \
- [ "$COMMIT_SIBLING_POSITION" = "FIRSTLAST" ] ; then
- # echo swap and destroy $tmpgrp
- sudo ipset --swap $tmpgrp "$VAR(../@)";
- sudo ipset --destroy $tmpgrp;
- rm -f $tmpfile;
- fi;
diff --git a/templates/firewall/modify/node.def b/templates/firewall/modify/node.def
index e1f82f3..640a89c 100644
--- a/templates/firewall/modify/node.def
+++ b/templates/firewall/modify/node.def
@@ -24,6 +24,7 @@ end: if sudo /opt/vyatta/sbin/vyatta-firewall.pl --update-rules modify "$VAR(@)"
else
exit 1;
fi
+ sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=prune-deleted-sets
create: sudo /opt/vyatta/sbin/vyatta-firewall.pl --setup iptables modify
diff --git a/templates/firewall/name/node.def b/templates/firewall/name/node.def
index 7e9bc44..e8be1cd 100644
--- a/templates/firewall/name/node.def
+++ b/templates/firewall/name/node.def
@@ -24,6 +24,7 @@ end: if sudo /opt/vyatta/sbin/vyatta-firewall.pl --update-rules name "$VAR(@)" ;
else
exit 1;
fi
+ sudo /opt/vyatta/sbin/vyatta-ipset.pl --action=prune-deleted-sets
create: sudo /opt/vyatta/sbin/vyatta-firewall.pl --setup iptables name
diff --git a/templates/firewall/node.def b/templates/firewall/node.def
index 30b5330..6ee0386 100644
--- a/templates/firewall/node.def
+++ b/templates/firewall/node.def
@@ -1,4 +1,4 @@
-priority: 215
+priority: 199
help: Firewall
delete: # set conntrack table size to standard 16384 entries if fw disabled