+ my $vmdata = { openvz => $openvz, qemu => $qemu };
+
+ return $vmdata;
+};
+
+sub read_vm_firewall_rules {
+ my ($vmdata) = @_;
+ my $rules = {};
+ foreach my $vmid (keys %{$vmdata->{qemu}}, keys %{$vmdata->{openvz}}) {
+ my $filename = "/etc/pve/firewall/$vmid.fw";
+ my $fh = IO::File->new($filename, O_RDONLY);
+ next if !$fh;
+
+ $rules->{$vmid} = parse_fw_rules($filename, $fh);
+ }
+
+ return $rules;
+}
+
+sub compile {
+ my $vmdata = read_local_vm_config();
+ my $rules = read_vm_firewall_rules($vmdata);
+
+ #print Dumper($rules);
+
+ my $ruleset = {};
+
+ # setup host firewall rules
+ ruleset_create_chain($ruleset, "PVEFW-INPUT");
+ ruleset_create_chain($ruleset, "PVEFW-OUTPUT");
+
+ enablehostfw($ruleset);
+
+ # generate firewall rules for QEMU VMs
+ foreach my $vmid (keys %{$vmdata->{qemu}}) {
+ my $conf = $vmdata->{qemu}->{$vmid};
+ next if !$rules->{$vmid};
+
+ foreach my $netid (keys %$conf) {
+ next if $netid !~ m/^net(\d+)$/;
+ my $net = PVE::QemuServer::parse_net($conf->{$netid});
+ next if !$net;
+ my $iface = "tap${vmid}i$1";
+
+ my $bridge = $net->{bridge};
+ next if !$bridge; # fixme: ?
+
+ $bridge .= "v$net->{tag}" if $net->{tag};
+
+ generate_bridge_chains($ruleset, $bridge);
+
+ my $macaddr = $net->{macaddr};
+ generate_tap_rules_direction($ruleset, $iface, $netid, $macaddr, $rules->{$vmid}->{in}, $bridge, 'IN');
+ generate_tap_rules_direction($ruleset, $iface, $netid, $macaddr, $rules->{$vmid}->{out}, $bridge, 'OUT');
+ }
+ }
+ return $ruleset;
+}
+
+sub get_ruleset_status {
+ my ($ruleset, $verbose) = @_;
+
+ my $active_chains = iptables_get_chains();
+
+ my $statushash = {};
+
+ foreach my $chain (sort keys %$ruleset) {
+ my $digest = Digest::SHA->new('sha1');
+ foreach my $cmd (@{$ruleset->{$chain}}) {
+ $digest->add("$cmd\n");
+ }
+ my $sig = $digest->b64digest;
+ $statushash->{$chain}->{sig} = $sig;
+
+ my $oldsig = $active_chains->{$chain};
+ if (!defined($oldsig)) {
+ $statushash->{$chain}->{action} = 'create';
+ } else {
+ if ($oldsig eq $sig) {
+ $statushash->{$chain}->{action} = 'exists';
+ } else {
+ $statushash->{$chain}->{action} = 'update';