From d9d081199c25864bd05badf41bd21f74c308ed9d Mon Sep 17 00:00:00 2001 From: Mikhail Zholobov Date: Tue, 9 Aug 2016 22:11:12 +0300 Subject: [PATCH] action/network: Validate IP settings, show human-readable error --- .../providers/virtualbox/action/network.rb | 35 ++++++++++--------- templates/locales/en.yml | 6 ++-- .../virtualbox/action/network_test.rb | 18 ++++++++++ 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/plugins/providers/virtualbox/action/network.rb b/plugins/providers/virtualbox/action/network.rb index d0c9aeb6e..e4e65aa62 100644 --- a/plugins/providers/virtualbox/action/network.rb +++ b/plugins/providers/virtualbox/action/network.rb @@ -261,16 +261,25 @@ module VagrantPlugins begin ip = IPAddr.new(options[:ip]) - rescue IPAddr::InvalidAddressError => e - raise Vagrant::Errors::NetworkAddressInvalid, :ip => options[:ip], :error_msg => e.message + 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 = IPAddr.new("#{options[:ip]}/#{options[:netmask]}") + rescue IPAddr::Error => e + raise Vagrant::Errors::NetworkAddressInvalid, + options: options, error: e.message end if ip.ipv4? - options[:netmask] ||= "255.255.255.0" - - # Calculate our network address for the given IP/netmask - netaddr = network_address(options[:ip], options[:netmask]) - # Verify that a host-only network subnet would not collide # with a bridged networking interface. # @@ -287,20 +296,12 @@ module VagrantPlugins interface_name: interface[:name] end 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 + 1. Usually it is "x.x.x.1" for IPv4 and # "::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 @@ -309,7 +310,7 @@ module VagrantPlugins # 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 diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 00c17fed0..fb8fa946f 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -972,10 +972,10 @@ en: network_type_not_supported: |- The %{type} network type is not supported for this box or guest. network_address_invalid: |- - The IP address '%{ip}' is not valid. Please review the error message - below to help resolve the issue: + Network settings specified in your Vagrantfile are invalid: - %{error_msg} + Network settings: %{options} + Error: %{error} network_manager_not_installed: |- Vagrant was instructed to configure the %{device} network device to be managed by NetworkManager. However, the configured guest VM does diff --git a/test/unit/plugins/providers/virtualbox/action/network_test.rb b/test/unit/plugins/providers/virtualbox/action/network_test.rb index 5c1eae212..34ed17d94 100644 --- a/test/unit/plugins/providers/virtualbox/action/network_test.rb +++ b/test/unit/plugins/providers/virtualbox/action/network_test.rb @@ -182,6 +182,24 @@ describe VagrantPlugins::ProviderVirtualBox::Action::Network do 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::NetworkAddressInvalid) + end + end + end + describe "#hostonly_find_matching_network" do let(:ip){ "192.168.55.2" } let(:config){ {ip: ip, netmask: "255.255.255.0"} }