Skip to content

Commit

Permalink
action/network: Validate IP settings, show human-readable error
Browse files Browse the repository at this point in the history
  • Loading branch information
legal90 committed May 2, 2017
1 parent 8fa033d commit 3077ee3
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 17 deletions.
4 changes: 4 additions & 0 deletions lib/vagrant/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,10 @@ class NetworkDHCPAlreadyAttached < VagrantError
error_key(:dhcp_already_attached, "vagrant.actions.vm.network")
end

class NetworkInvalidAddress < VagrantError
error_key(:network_invalid_address)
end

class NetworkNotFound < VagrantError
error_key(:not_found, "vagrant.actions.vm.host_only_network")
end
Expand Down
40 changes: 23 additions & 17 deletions plugins/providers/virtualbox/action/network.rb
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,27 @@ def hostonly_config(options)
# Default IP is in the 20-bit private network block for DHCP based networks
options[:ip] = "172.28.128.1" if options[:type] == :dhcp && !options[:ip]

ip = IPAddr.new(options[:ip])
if ip.ipv4?
options[:netmask] ||= "255.255.255.0"
begin
ip = IPAddr.new(options[:ip])
if ip.ipv4?
options[:netmask] ||= "255.255.255.0"
elsif ip.ipv6?
options[:netmask] ||= 64

# Append a 6 to the end of the type
options[:type] = "#{options[:type]}6".to_sym
else
raise IPAddr::AddressFamilyError, 'unknown address family'
end

# Calculate our network address for the given IP/netmask
netaddr = network_address(options[:ip], options[:netmask])
netaddr = IPAddr.new("#{options[:ip]}/#{options[:netmask]}")
rescue IPAddr::Error => e
raise Vagrant::Errors::NetworkInvalidAddress,
options: options, error: e.message
end

if ip.ipv4?
# Verify that a host-only network subnet would not collide
# with a bridged networking interface.
#
Expand All @@ -273,24 +287,16 @@ def hostonly_config(options)
# traffic onto the real interface rather than the VirtualBox
# interface.
@env[:machine].provider.driver.read_bridged_interfaces.each do |interface|
that_netaddr = network_address(interface[:ip], interface[:netmask])
raise Vagrant::Errors::NetworkCollision if \
netaddr == that_netaddr && interface[:status] != "Down"
next if interface[:status] == "Down"
that_netaddr = IPAddr.new("#{interface[:ip]}/#{interface[:netmask]}")
raise Vagrant::Errors::NetworkCollision if netaddr.include? that_netaddr
end
elsif ip.ipv6?
# Default subnet prefix length
options[:netmask] ||= 64

# Append a 6 to the end of the type
options[:type] = "#{options[:type]}6".to_sym
else
raise "BUG: Unknown IP type: #{ip.inspect}"
end

# Calculate the adapter IP which is the network address with the final
# bit group appended by 1. Usually it is "x.x.x.1" for IPv4 and
# "<prefix>::1" for IPv6
options[:adapter_ip] ||= (ip.mask(options[:netmask]) | 1).to_s
options[:adapter_ip] ||= (netaddr | 1).to_s

dhcp_options = {}
if options[:type] == :dhcp
Expand All @@ -299,7 +305,7 @@ def hostonly_config(options)
# dhcp_ip: "192.168.22.66",
# dhcp_lower: "192.168.22.67"
# dhcp_upper: "192.168.22.126"
ip_range = ip.mask(options[:netmask]).to_range
ip_range = netaddr.to_range
dhcp_options[:dhcp_ip] = options[:dhcp_ip] || (ip_range.first | 2).to_s
dhcp_options[:dhcp_lower] = options[:dhcp_lower] || (ip_range.first | 3).to_s
dhcp_options[:dhcp_upper] = options[:dhcp_upper] || (ip_range.last(2).first).to_s
Expand Down
5 changes: 5 additions & 0 deletions templates/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,11 @@ en:
If the problem persists, please report a bug to the net-ssh project.
%{message}
network_invalid_address: |-
Network settings specified in your Vagrantfile are invalid:
Network settings: %{options}
Error: %{error}
network_type_not_supported: |-
The %{type} network type is not supported for this box or guest.
network_manager_not_installed: |-
Expand Down
18 changes: 18 additions & 0 deletions test/unit/plugins/providers/virtualbox/action/network_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,22 @@
end
end
end

context 'with invalid settings' do
[
{ ip: 'foo'},
{ ip: '1.2.3'},
{ ip: 'dead::beef::'},
{ ip: '172.28.128.3', netmask: 64},
{ ip: '172.28.128.3', netmask: 'ffff:ffff::'},
{ ip: 'dead:beef::', netmask: 'foo:bar::'},
{ ip: 'dead:beef::', netmask: '255.255.255.0'}
].each do |args|
it 'raises an exception' do
machine.config.vm.network 'private_network', **args
expect { subject.call(env) }.
to raise_error(Vagrant::Errors::NetworkInvalidAddress)
end
end
end
end

0 comments on commit 3077ee3

Please sign in to comment.