read in shorewall macros
[pve-firewall.git] / PVE / Firewall.pm
index 3d7d9eb..c9f502a 100644 (file)
@@ -6,6 +6,19 @@ use Data::Dumper;
 use PVE::Tools;
 use PVE::QemuServer;
 
+my $macros;
+sub get_shorewall_macros {
+
+    return $macros if $macros;
+
+    foreach my $path (</usr/share/shorewall/macro.*>) {
+       if ($path =~ m|/macro\.(\S+)$|) {
+           $macros->{$1} = 1;
+       }
+    }
+    return $macros;
+}
+
 
 my $rule_format = "%-15s %-15s %-15s %-15s %-15s %-15s\n";
 
@@ -18,8 +31,11 @@ my $generate_input_rule = sub {
     my $zone = $net->{zone} || die "internal error";
     my $zid = $zoneinfo->{$zone}->{id} || die "internal error";
     my $tap = $net->{tap} || die "internal error";
-    
-    return sprintf($rule_format, $rule->{action}, $rule->{source}, "$zid:$tap", 
+
+    my $action = $rule->{service} ? 
+       "$rule->{service}($rule->{action})" : $rule->{action};
+
+    return sprintf($rule_format, $action, $rule->{source}, "$zid:$tap", 
                   $rule->{proto} || '-', $rule->{dport} || '-', $rule->{sport} || '-');
 };
 
@@ -32,8 +48,11 @@ my $generate_output_rule = sub {
     my $zone = $net->{zone} || die "internal error";
     my $zid = $zoneinfo->{$zone}->{id} || die "internal error";
     my $tap = $net->{tap} || die "internal error";
+
+    my $action = $rule->{service} ? 
+       "$rule->{service}($rule->{action})" : $rule->{action};
     
-    return sprintf($rule_format, $rule->{action}, "$zid:$tap", $rule->{dest}, 
+    return sprintf($rule_format, $action, "$zid:$tap", $rule->{dest}, 
                   $rule->{proto} || '-', $rule->{dport} || '-', $rule->{sport} || '-');
 };
 
@@ -43,12 +62,19 @@ my $generate_output_rule = sub {
 sub compile {
     my ($targetdir, $vmdata, $rules) = @_;
 
+    # remove existing data ?
+    foreach my $file (qw(zones rules interfaces  maclist  policy)) {
+       unlink "$targetdir/$file";
+    }
+
     my $netinfo;
 
     my $zoneinfo = {
        fw => { type => 'firewall' },
     };
 
+    my $maclist = {};
+
     my $register_bridge;
 
     $register_bridge = sub {
@@ -99,6 +125,7 @@ sub compile {
 
            my $vmzone = $conf->{zone} || "vm$vmid";
            $net->{tap} = "tap${vmid}i${netnum}";
+           $maclist->{$net->{tap}} = $net->{macaddr} || die "internal error";
            $net->{zone} = &$register_bridge_port($net->{bridge}, $net->{tag}, $vmzone, $net->{tap});
            $netinfo->{$vmid}->{$opt} = $net;
        }
@@ -156,13 +183,16 @@ sub compile {
     $format = "%-15s %-20s %-10s %-15s %s\n";
     $out = sprintf($format, '#ZONE', 'INTERFACE', 'BROADCAST', 'OPTIONS', '');
 
+    my $maclist_format = "%-15s %-15s %-15s\n";
+    my $macs = sprintf($maclist_format, '#DISPOSITION', 'INTERFACE', 'MACZONE');
+
     foreach my $z (sort keys %$zoneinfo) {
        my $zid = $zoneinfo->{$z}->{id};
        if ($zoneinfo->{$z}->{type} eq 'firewall') {
            # do nothing;
        } elsif ($zoneinfo->{$z}->{type} eq 'bridge') {
            my $bridge = $zoneinfo->{$z}->{bridge} || die "internal error";
-           $out .= sprintf($format, $zid, $bridge, 'detect', 'bridge', "# $z");
+           $out .= sprintf($format, $zid, $bridge, 'detect', 'bridge,optional', "# $z");
 
        } elsif ($zoneinfo->{$z}->{type} eq 'bport') {
            my $ifaces = $zoneinfo->{$z}->{ifaces};
@@ -170,7 +200,8 @@ sub compile {
                my $bridge_zone = $zoneinfo->{$z}->{bridge_zone} || die "internal error";
                my $bridge = $zoneinfo->{$bridge_zone}->{bridge} || die "internal error";
                my $iftxt = "$bridge:$iface";
-               $out .= sprintf($format, $zid, $iftxt, '', '', "# $z");
+               $out .= sprintf($format, $zid, $iftxt, '-', 'maclist', "# $z");
+               $macs .= sprintf($maclist_format, 'ACCEPT', $iface, $maclist->{$iface});
            }
        } else {
            die "internal error";
@@ -181,10 +212,14 @@ sub compile {
 
     PVE::Tools::file_set_contents("$targetdir/interfaces", $out);
 
+    # dump maclist
+    PVE::Tools::file_set_contents("$targetdir/maclist", $macs);
+
     # dump policy
 
     $format = "%-15s %-15s %-15s %s\n";
     $out = sprintf($format, '#SOURCE', 'DEST', 'POLICY', 'LOG');
+    #$out .= sprintf($format, 'fw', 'all', 'ACCEPT', '');
     $out .= sprintf($format, 'all', 'all', 'REJECT', 'info');
 
     PVE::Tools::file_set_contents("$targetdir/policy", $out);