summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2011-05-20 12:09:01 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2011-05-20 12:09:01 -0700
commit7a753ec2407d775635adc0df54dac21f59950ecb (patch)
treee88ce2989d1dab01dd50d85f7d89bd4307819d66
parent612036432f576162e83d14172700e4823154f5ad (diff)
downloadvyatta-cfg-firewall-7a753ec2407d775635adc0df54dac21f59950ecb.tar.gz
vyatta-cfg-firewall-7a753ec2407d775635adc0df54dac21f59950ecb.zip
add "two-stage commit" equivalent to previous fix for bug 5227.
-rwxr-xr-xscripts/firewall/vyatta-ipset.pl40
1 files changed, 34 insertions, 6 deletions
diff --git a/scripts/firewall/vyatta-ipset.pl b/scripts/firewall/vyatta-ipset.pl
index 7ee7bdc..5dfe3a9 100755
--- a/scripts/firewall/vyatta-ipset.pl
+++ b/scripts/firewall/vyatta-ipset.pl
@@ -203,7 +203,7 @@ sub ipset_is_group_used {
sub update_set {
my ($set_name, $set_type) = @_;
my $cfg = new Vyatta::Config;
- my $rc;
+ my ($rc, $newset);
my $cpath = "firewall group $set_type-group $set_name";
if ($cfg->existsOrig($cpath)) {
if (!$cfg->exists($cpath)) {
@@ -215,6 +215,7 @@ sub update_set {
if ($cfg->exists($cpath)) {
# added
return $rc if (($rc = ipset_create($set_name, $set_type)));
+ $newset = 1;
} else {
# doesn't exist! should not happen
return "Updating non-existent group [$set_name]";
@@ -222,16 +223,43 @@ sub update_set {
}
# added or potentially changed => iterate members
+ # to ensure that vyatta config and ipset stay in-sync, do the following:
+ # 1. copy orig set to tmp set
+ my $tmpset = "$set_name-$$";
+ if (($rc = ipset_copy_set($set_name, $set_type, $tmpset))) {
+ # copy failed
+ if ($newset) {
+ # destroy newly-created set since we're failing
+ system('ipset', '--destroy', $set_name);
+ }
+ return $rc;
+ }
+
+ # 2. add/delete members to/from tmp set according to changes
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)));
+ while (1) {
+ for my $d (@{$vals{deleted}}) {
+ last if (($rc = ipset_delete_member($tmpset, $d)));
+ }
+ last if ($rc);
+ for my $a (@{$vals{added}}) {
+ last if (($rc = ipset_add_member($tmpset, $a, $set_name)));
+ }
+ last;
}
- for my $a (@{$vals{added}}) {
- return $rc if (($rc = ipset_add_member($set_name, $a)));
+
+ # 3. "commit" changes and/or clean up
+ if (!$rc) {
+ # no error
+ system('ipset', '--swap', $tmpset, $set_name);
+ } elsif ($newset) {
+ # destroy newly-created set since we're failing
+ system('ipset', '--destroy', $set_name);
}
- exit 0;
+ system('ipset', '--destroy', $tmpset);
+ return $rc;
}
sub prune_deleted_sets {