'Ping' => [
{ action => 'PARAM', proto => 'icmpv6', dport => 'echo-request' },
],
+ 'NeighborDiscovery' => [
+ "IPv6 neighbor solicitation, neighbor and router advertisement",
+ { action => 'PARAM', proto => 'icmpv6', dport => 'router-advertisement' },
+ { action => 'PARAM', proto => 'icmpv6', dport => 'neighbor-solicitation' },
+ { action => 'PARAM', proto => 'icmpv6', dport => 'neighbor-advertisement' },
+ ],
'Trcrt' => [
{ action => 'PARAM', proto => 'udp', dport => '33434:33524' },
{ action => 'PARAM', proto => 'icmpv6', dport => 'echo-request' },
my $pve_fw_parsed_macros;
my $pve_fw_macro_descr;
+my $pve_fw_macro_ipversion = {};
my $pve_fw_preferred_macro_names = {};
my $pve_std_chains = {};
$pve_fw_parsed_macros = {};
- foreach my $k (keys %$pve_fw_macros) {
+ my $parse = sub {
+ my ($k, $macro) = @_;
my $lc_name = lc($k);
- my $macro = $pve_fw_macros->{$k};
- if (!ref($macro->[0])) {
- $pve_fw_macro_descr->{$k} = shift @$macro;
+ $pve_fw_macro_ipversion->{$k} = 0;
+ while (!ref($macro->[0])) {
+ my $desc = shift @$macro;
+ if ($desc eq 'ipv4only') {
+ $pve_fw_macro_ipversion->{$k} = 4;
+ } elsif ($desc eq 'ipv6only') {
+ $pve_fw_macro_ipversion->{$k} = 6;
+ } else {
+ $pve_fw_macro_descr->{$k} = $desc;
+ }
}
$pve_fw_preferred_macro_names->{$lc_name} = $k;
$pve_fw_parsed_macros->{$k} = $macro;
+ };
+
+ foreach my $k (keys %$pve_fw_macros) {
+ &$parse($k, $pve_fw_macros->{$k});
+ }
+
+ foreach my $k (keys %$pve_ipv6fw_macros) {
+ next if $pve_fw_parsed_macros->{$k};
+ &$parse($k, $pve_ipv6fw_macros->{$k});
+ $pve_fw_macro_ipversion->{$k} = 6;
}
}
my $testip = Net::IP->new($ip);
- my $routes = PVE::ProcFSTools::read_proc_net_route();
+ my $isv6 = $testip->version == 6;
+ my $routes = $isv6 ? PVE::ProcFSTools::read_proc_net_ipv6_route()
+ : PVE::ProcFSTools::read_proc_net_route();
foreach my $entry (@$routes) {
- my $mask = $ipv4_mask_hash_localnet->{$entry->{mask}};
- next if !defined($mask);
- return if $mask eq '0.0.0.0';
+ my $mask;
+ if ($isv6) {
+ $mask = $entry->{prefix};
+ } else {
+ $mask = $ipv4_mask_hash_localnet->{$entry->{mask}};
+ next if !defined($mask);
+ }
my $cidr = "$entry->{dest}/$mask";
my $testnet = Net::IP->new($cidr);
- if ($testnet->overlaps($testip)) {
+ if ($testnet->overlaps($testip) == $Net::IP::IP_B_IN_A_OVERLAP) {
$__local_network = $cidr;
return;
}
$macro_rules = $pve_ipv6fw_macros->{$macro_name};
}
+ # skip macros which are specific to another ipversion
+ if ($ipversion && (my $required = $pve_fw_macro_ipversion->{$macro_name})) {
+ return if $ipversion != $required;
+ }
+
my $rules = [];
foreach my $templ (@$macro_rules) {
}
#http://backreference.org/2013/03/01/ipv6-address-normalization/
if ($ver == 6) {
- my $ipv6 = inet_pton(AF_INET6, lc($cidr));
- $cidr = inet_ntop(AF_INET6, $ipv6);
+ $cidr = lc(Net::IP::ip_compress_address($cidr, 6));
$cidr =~ s|/128$||;
} else {
$cidr =~ s|/32$||;