From ea41223e928708d65f3c01bcbd0b573042de4f5c Mon Sep 17 00:00:00 2001 From: Steve Wills Date: Tue, 1 Nov 2016 22:16:22 -0400 Subject: [PATCH] Avoid hard coding network address for bridge Add functions to examine local subnets and avoid using a network that is already in use locally. More may be needed, but this avoids a local issue for now. Note this will only work on 11.0 and later since it uses the libxo support in netstat. --- lib/vagrant-bhyve/driver.rb | 68 +++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/vagrant-bhyve/driver.rb b/lib/vagrant-bhyve/driver.rb index 933d611..a0dcc6b 100644 --- a/lib/vagrant-bhyve/driver.rb +++ b/lib/vagrant-bhyve/driver.rb @@ -3,7 +3,8 @@ require "digest/md5" require "io/console" require "ruby_expect" - +require "json" +require "ipaddr" module VagrantPlugins module ProviderBhyve @@ -210,7 +211,7 @@ def enable_nat(bridge, ui) # Choose a subnet for this bridge index = bridge_name =~ /\d/ bridge_num = bridge_name[index..-1] - sub_net = "172.16." + bridge_num + sub_net = _find_free_net.split('.')[0,2].join(".") + "." + bridge_num # Config IP for the bridge execute(false, "#{@sudo} ifconfig #{bridge_name} #{sub_net}.1/24") @@ -669,6 +670,69 @@ def grub_bhyve_execute(command, password, member) end end + def _find_local_subnets() + netstat4_json = `netstat -rn -4 --libxo json` + my_routes4_json = JSON.parse(netstat4_json) + + my_routes4 = my_routes4_json['statistics']['route-information']['route-table']['rt-family'][0]['rt-entry'] + + local_nets = [] + my_routes4.each do |route| + next if route['destination'] == "default" + local_nets.push(route['destination']) + end + return local_nets + end + + def _ip_in_subnet(ip, net) + netaddr = IPAddr.new(net) + return netaddr === IPAddr.new(ip) + end + + def _find_free_net() + local_networks = _find_local_subnets + + # largest to smallest + (0..255).each do |i| + ip = "10." + i.to_s + ".0.0" + found = false + local_networks.each do |net| + if _ip_in_subnet(ip, net) + found = true + end + end + if found == false + return ip.to_s + "/8" + end + end + + (16..31).each do |i| + ip = "172." + i.to_s + ".0.0" + found = false + local_networks.each do |net| + if _ip_in_subnet(ip, net) + found = true + end + end + if found == false + return ip.to_s + "/16" + end + end + + (0..255).each do |i| + ip = "192.168." + i.to_s + ".0" + found = false + local_networks.each do |net| + if _ip_in_subnet(ip, net) + found = true + end + end + if found == false + return ip.to_s + "/24" + end + end + end # _find_free_net + end end end