Skip to content

Commit c584b8e

Browse files
committed
Merge pull request docker-archive-public#2625 from dgageot/2624-reject-duplicate-hostonlyifs
FIX docker-archive-public#2624 reject duplicate hostonlyifs name/IP
2 parents 352d282 + 3c4fd63 commit c584b8e

File tree

3 files changed

+51
-26
lines changed

3 files changed

+51
-26
lines changed

drivers/virtualbox/network.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ const (
1313
)
1414

1515
var (
16-
reHostonlyInterfaceCreated = regexp.MustCompile(`Interface '(.+)' was successfully created`)
17-
errDuplicateHostOnlyInterfaceNetworks = errors.New("VirtualBox is configured with multiple host-only interfaces with the same IP. Please remove all of them but one.")
18-
errNewHostOnlyInterfaceNotVisible = errors.New("The host-only interface we just created is not visible. This is a well known bug of VirtualBox. You might want to uninstall it and reinstall the version listed here: https://www.virtualbox.org/ticket/14437?cversion=0&cnum_hist=42")
16+
reHostonlyInterfaceCreated = regexp.MustCompile(`Interface '(.+)' was successfully created`)
17+
errNewHostOnlyInterfaceNotVisible = errors.New("The host-only interface we just created is not visible. This is a well known bug of VirtualBox. You might want to uninstall it and reinstall the version listed here: https://www.virtualbox.org/ticket/14437?cversion=0&cnum_hist=42")
1918
)
2019

2120
// Host-only network.
@@ -75,7 +74,8 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
7574
return nil, err
7675
}
7776

78-
m := map[string]*hostOnlyNetwork{}
77+
byName := map[string]*hostOnlyNetwork{}
78+
byIP := map[string]*hostOnlyNetwork{}
7979
n := &hostOnlyNetwork{}
8080

8181
err = parseKeyValues(out, reColonLine, func(key, val string) error {
@@ -110,7 +110,19 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
110110
n.Status = val
111111
case "VBoxNetworkName":
112112
n.NetworkName = val
113-
m[val] = n
113+
114+
if _, present := byName[n.NetworkName]; present {
115+
return fmt.Errorf("VirtualBox is configured with multiple host-only interfaces with the same name %q. Please remove one.", n.NetworkName)
116+
}
117+
byName[n.NetworkName] = n
118+
119+
if len(n.IPv4.IP) != 0 {
120+
if _, present := byIP[n.IPv4.IP.String()]; present {
121+
return fmt.Errorf("VirtualBox is configured with multiple host-only interfaces with the same IP %q. Please remove one.", n.IPv4.IP)
122+
}
123+
byIP[n.IPv4.IP.String()] = n
124+
}
125+
114126
n = &hostOnlyNetwork{}
115127
}
116128

@@ -120,7 +132,7 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
120132
return nil, err
121133
}
122134

123-
return m, nil
135+
return byName, nil
124136
}
125137

126138
func getHostOnlyNetwork(nets map[string]*hostOnlyNetwork, hostIP net.IP, netmask net.IPMask) *hostOnlyNetwork {
@@ -143,10 +155,6 @@ func getOrCreateHostOnlyNetwork(hostIP net.IP, netmask net.IPMask, dhcpIP net.IP
143155
return nil, err
144156
}
145157

146-
if len(nets) != countUniqueIps(nets) {
147-
return nil, errDuplicateHostOnlyInterfaceNetworks
148-
}
149-
150158
hostOnlyNet := getHostOnlyNetwork(nets, hostIP, netmask)
151159
if hostOnlyNet != nil {
152160
return hostOnlyNet, nil
@@ -188,16 +196,6 @@ func getOrCreateHostOnlyNetwork(hostIP net.IP, netmask net.IPMask, dhcpIP net.IP
188196
return hostOnlyNet, nil
189197
}
190198

191-
func countUniqueIps(nets map[string]*hostOnlyNetwork) int {
192-
ips := map[string]bool{}
193-
194-
for _, n := range nets {
195-
ips[n.IPv4.IP.String()] = true
196-
}
197-
198-
return len(ips)
199-
}
200-
201199
// DHCP server info.
202200
type dhcpServer struct {
203201
NetworkName string

drivers/virtualbox/network_test.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ VBoxNetworkName: HostInterfaceNetworking-vboxnet0
3939
Name: vboxnet1
4040
GUID: 786f6276-656e-4174-8000-0a0027000001
4141
DHCP: Disabled
42-
IPAddress: 192.168.99.1
42+
IPAddress: 169.254.37.187
4343
NetworkMask: 255.255.255.0
4444
IPV6Address:
4545
IPV6NetworkMaskPrefixLength: 0
@@ -185,7 +185,7 @@ func TestListTwoHostOnlyNetworks(t *testing.T) {
185185
assert.Equal(t, "vboxnet1", net.Name)
186186
assert.Equal(t, "786f6276-656e-4174-8000-0a0027000001", net.GUID)
187187
assert.False(t, net.DHCP)
188-
assert.Equal(t, "192.168.99.1", net.IPv4.IP.String())
188+
assert.Equal(t, "169.254.37.187", net.IPv4.IP.String())
189189
assert.Equal(t, "ffffff00", net.IPv4.Mask.String())
190190
assert.Empty(t, net.IPv6.IP)
191191
assert.Equal(t, "0a:00:27:00:00:01", net.HwAddr.String())
@@ -230,16 +230,38 @@ func TestGetHostOnlyNetwork(t *testing.T) {
230230
assert.NoError(t, err)
231231
}
232232

233-
func TestFailWithDuplicateHostOnlyNetworks(t *testing.T) {
233+
func TestFailIfTwoNetworksHaveSameIP(t *testing.T) {
234234
vbox := &VBoxManagerMock{
235-
args: "list hostonlyifs",
236-
stdOut: stdOutTwoHostOnlyNetwork,
235+
args: "list hostonlyifs",
236+
stdOut: `Name: vboxnet0
237+
IPAddress: 192.168.99.1
238+
NetworkMask: 255.255.255.0
239+
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
240+
Name: vboxnet1
241+
IPAddress: 192.168.99.1
242+
NetworkMask: 255.255.255.0
243+
VBoxNetworkName: HostInterfaceNetworking-vboxnet1`,
244+
}
245+
246+
net, err := getOrCreateHostOnlyNetwork(net.ParseIP("192.168.99.1"), parseIPv4Mask("255.255.255.0"), nil, nil, nil, vbox)
247+
248+
assert.Nil(t, net)
249+
assert.EqualError(t, err, `VirtualBox is configured with multiple host-only interfaces with the same IP "192.168.99.1". Please remove one.`)
250+
}
251+
252+
func TestFailIfTwoNetworksHaveSameName(t *testing.T) {
253+
vbox := &VBoxManagerMock{
254+
args: "list hostonlyifs",
255+
stdOut: `Name: vboxnet0
256+
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
257+
Name: vboxnet0
258+
VBoxNetworkName: HostInterfaceNetworking-vboxnet0`,
237259
}
238260

239261
net, err := getOrCreateHostOnlyNetwork(net.ParseIP("192.168.99.1"), parseIPv4Mask("255.255.255.0"), nil, nil, nil, vbox)
240262

241263
assert.Nil(t, net)
242-
assert.Equal(t, errDuplicateHostOnlyInterfaceNetworks, err)
264+
assert.EqualError(t, err, `VirtualBox is configured with multiple host-only interfaces with the same name "HostInterfaceNetworking-vboxnet0". Please remove one.`)
243265
}
244266

245267
func TestGetDHCPServers(t *testing.T) {

drivers/virtualbox/virtualbox.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ func (d *Driver) PreCreateCheck() error {
226226
return err
227227
}
228228

229+
// Check that Host-only interfaces are ok
230+
if _, err = listHostOnlyNetworks(d.VBoxManager); err != nil {
231+
return err
232+
}
233+
229234
return nil
230235
}
231236

0 commit comments

Comments
 (0)