Skip to content

Commit

Permalink
Workaround for IPv6Net /64 anomaly in netaddr gem
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianNachtigall committed Apr 7, 2022
1 parent d40d9b7 commit 3414bce
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 12 deletions.
8 changes: 6 additions & 2 deletions src/bosh-director/lib/bosh/director/ip_util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,17 @@ def to_s
private

def parse(cidr)
NetAddr::IPv4Net.parse(cidr)
cidr = NetAddr::IPv4Net.parse(cidr)
rescue NetAddr::ValidationError => e_v4
begin
NetAddr::IPv6Net.parse(cidr)
cidr = NetAddr::IPv6Net.parse(cidr)
if cidr.netmask.prefix_len <= 64
raise "Unsupported CIDR prefix length. Please choose a CIDR mask numerically larger than /64."
end
rescue NetAddr::ValidationError => e_v6
raise NetAddr::ValidationError, "IP CIDR format #{ip} is neither a valid IPv4 nor IPv6 format: #{e_v4} / #{e_v6}"
end
cidr
end
end

Expand Down
4 changes: 2 additions & 2 deletions src/bosh-director/spec/unit/cidr_range_combiner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ module Bosh::Director
[
NetAddr::IPv4Net.parse('192.168.0.8/30'),
NetAddr::IPv6Net.parse('fd7a:eeed:e696:968f:0000:0000:0000:0005/128'),
NetAddr::IPv6Net.parse('fd7a:eeed:e696:968f:0000:0000:0000:0005/64'),
NetAddr::IPv6Net.parse('fd7a:eeed:e696:968f:0000:0000:0000:0005/96'),
NetAddr::IPv4Net.parse('192.168.0.20/32'),
]
end

it 'combines the ranges' do
expect(range_combiner.combine_ranges(cidr_ranges)).to eq(
[['192.168.0.8', '192.168.0.11'], ['192.168.0.20', '192.168.0.20'],
['fd7a:eeed:e696:968f:0000:0000:0000:0000', 'fd7a:eeed:e696:968f:ffff:ffff:ffff:ffff']],
['fd7a:eeed:e696:968f::', 'fd7a:eeed:e696:968f::ffff:ffff']],
)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def create_dynamic_reservation(ip)
it 'should create an IPv6 subnet spec' do
subnet = make_subnet(
{
'range' => 'fdab:d85c:118d:8a46::/64',
'range' => 'fdab:d85c:118d:8a46::/96',
'gateway' => 'fdab:d85c:118d:8a46::1',
'reserved' => [
'fdab:d85c:118d:8a46::10-fdab:d85c:118d:8a46::ff',
Expand All @@ -105,16 +105,29 @@ def create_dynamic_reservation(ip)
[],
)

expect(subnet.range.ip).to eq('fdab:d85c:118d:8a46:0000:0000:0000:0000')
subnet.range.ip.size == 2**64
expect(subnet.netmask).to eq('ffff:ffff:ffff:ffff:0000:0000:0000:0000')
expect(subnet.gateway).to eq('fdab:d85c:118d:8a46:0000:0000:0000:0001')
expect(subnet.range.network.to_s).to eq('fdab:d85c:118d:8a46::')
# subnet.range.ip.size == 2**64 # TODO NETADDR: bug? / what was tested here?
expect(subnet.netmask).to eq('ffff:ffff:ffff:ffff:ffff:ffff::')
expect(subnet.gateway.to_s).to eq('fdab:d85c:118d:8a46::1') # TODO NETADDR: not sure how it worked before (was previously an object as well)
expect(subnet.dns).to eq([
"2001:4860:4860:0000:0000:0000:0000:8888",
"2001:4860:4860:0000:0000:0000:0000:8844",
"2001:4860:4860::8888",
"2001:4860:4860::8844",
])
end

it 'should fail for <= /64 IPv6 CIDR prefixes' do
expect {
make_subnet(
{
'range' => 'fdab:d85c:118d:8a46::/64',
'gateway' => 'fdab:d85c:118d:8a46::1',
'cloud_properties' => {'foo' => 'bar'},
},
[]
)
}.to raise_error(/Unsupported CIDR prefix length/)
end

it 'should require a range' do
expect {
make_subnet(
Expand Down Expand Up @@ -385,7 +398,7 @@ def create_dynamic_reservation(ip)
it 'should return false when IPv4 and IPv6 ranges are compared' do
other = make_subnet(
{
'range' => 'f1ee:0000:0000:0000:0000:0000:0000:0000/64',
'range' => 'f1ee:0000:0000:0000:0000:0000:0000:0000/96',
'gateway' => 'f1ee:0000:0000:0000:0000:0000:0000:0001',
'cloud_properties' => { 'foo' => 'bar' },
},
Expand Down

0 comments on commit 3414bce

Please sign in to comment.