diff --git a/lib/vagrant/util/network_ip.rb b/lib/vagrant/util/network_ip.rb index 1a4653656..8930bc36a 100644 --- a/lib/vagrant/util/network_ip.rb +++ b/lib/vagrant/util/network_ip.rb @@ -3,11 +3,21 @@ require "ipaddr" module Vagrant module Util module NetworkIP + + DEFAULT_MASK = "255.255.255.0".freeze + + LOGGER = Log4r::Logger.new("vagrant::util::NetworkIP") + # Returns the network address of the given IP and subnet. # # @return [String] def network_address(ip, subnet) - IPAddr.new(ip).mask(subnet).to_s + begin + IPAddr.new(ip).mask(subnet).to_s + rescue IPAddr::InvalidPrefixError + LOGGER.warn("Provided mask '#{subnet}' is invalid. Falling back to using mask '#{DEFAULT_MASK}'") + IPAddr.new(ip).mask(DEFAULT_MASK).to_s + end end end end diff --git a/test/unit/vagrant/util/network_ip_test.rb b/test/unit/vagrant/util/network_ip_test.rb index 5351f4f9a..181b642cb 100644 --- a/test/unit/vagrant/util/network_ip_test.rb +++ b/test/unit/vagrant/util/network_ip_test.rb @@ -5,33 +5,47 @@ require "vagrant/util/network_ip" describe Vagrant::Util::NetworkIP do let(:klass) do Class.new do - extend Vagrant::Util::NetworkIP + include Vagrant::Util::NetworkIP end end - describe "network address" do + subject { klass.new } + + describe "#network_address" do it "calculates it properly" do - expect(klass.network_address("192.168.2.234", "255.255.255.0")).to eq("192.168.2.0") + expect(subject.network_address("192.168.2.234", "255.255.255.0")).to eq("192.168.2.0") end it "calculates it properly with integer submask" do - expect(klass.network_address("192.168.2.234", "24")).to eq("192.168.2.0") + expect(subject.network_address("192.168.2.234", "24")).to eq("192.168.2.0") end it "calculates it properly with integer submask" do - expect(klass.network_address("192.168.2.234", 24)).to eq("192.168.2.0") + expect(subject.network_address("192.168.2.234", 24)).to eq("192.168.2.0") end it "calculates it properly for IPv6" do - expect(klass.network_address("fde4:8dba:82e1::c4", "64")).to eq("fde4:8dba:82e1::") + expect(subject.network_address("fde4:8dba:82e1::c4", "64")).to eq("fde4:8dba:82e1::") end it "calculates it properly for IPv6" do - expect(klass.network_address("fde4:8dba:82e1::c4", 64)).to eq("fde4:8dba:82e1::") + expect(subject.network_address("fde4:8dba:82e1::c4", 64)).to eq("fde4:8dba:82e1::") end it "calculates it properly for IPv6 for string mask" do - expect(klass.network_address("fde4:8dba:82e1::c4", "ffff:ffff:ffff:ffff::")).to eq("fde4:8dba:82e1::") + expect(subject.network_address("fde4:8dba:82e1::c4", "ffff:ffff:ffff:ffff::")).to eq("fde4:8dba:82e1::") + end + + it "recovers from invalid netmask" do + # The mask function will produce an error for ruby >= 2.5 + # If using a version of ruby that produces and error, then + # test to ensure `subject.network_address` produces expected + # results. + begin + IPAddr.new("192.168.2.234").mask("1.2.3.4") + rescue IPAddr::InvalidPrefixError + expect(subject.network_address("192.168.2.234", "1.2.3.4")).to eq("192.168.2.0") + end end end end