Skip to content

Commit 7650346

Browse files
committed
pkg/hostagent: Fix detecting host IPs on the same subnet as the guest
Signed-off-by: Norio Nomura <norio.nomura@gmail.com>
1 parent 40cc180 commit 7650346

File tree

2 files changed

+65
-32
lines changed

2 files changed

+65
-32
lines changed

pkg/hostagent/hostagent.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ type HostAgent struct {
8989
guestIPv4 net.IP
9090
guestIPv6 net.IP
9191
guestIPMu sync.RWMutex
92+
93+
// Host interface name on the same subnet as the guest,
94+
hostIfnameOnSameSubnetAsGuest string
9295
// Host IP address on the same subnet as the guest.
9396
hostIPv4 net.IP
9497
hostIPv6 net.IP

pkg/hostagent/requirements.go

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"errors"
1010
"fmt"
1111
"net"
12+
"net/netip"
1213
"runtime"
1314
"strings"
1415
"time"
@@ -321,36 +322,19 @@ func (a *HostAgent) detectGuestIfnameOnSameSubnetAtHost(stdout string) error {
321322
if err != nil {
322323
return fmt.Errorf("failed to get network interfaces: %w", err)
323324
}
324-
var (
325-
guestIfnameOnSameSubnetAsHost string
326-
hostIPv4 net.IP
327-
hostIPv6 net.IP
328-
)
329325
for _, neighbor := range neighbors {
330326
for _, ifi := range interfaces {
331327
if ifi.HardwareAddr.String() != neighbor.LLADDR {
332328
continue
333329
}
334-
guestIfnameOnSameSubnetAsHost = neighbor.DEV
335-
if hostIP := net.ParseIP(neighbor.DST); hostIP.To4() != nil {
336-
hostIPv4 = hostIP
337-
} else if hostIP.To16() != nil {
338-
hostIPv6 = hostIP
339-
}
330+
a.guestIPMu.Lock()
331+
a.guestIfnameOnSameSubnetAsHost = neighbor.DEV
332+
a.hostIfnameOnSameSubnetAsGuest = ifi.Name
333+
a.guestIPMu.Unlock()
334+
logrus.Infof("Detected guest interface %q and host interface %q on the same subnet", neighbor.DEV, ifi.Name)
335+
return nil
340336
}
341337
}
342-
a.guestIPMu.Lock()
343-
a.guestIfnameOnSameSubnetAsHost = guestIfnameOnSameSubnetAsHost
344-
a.hostIPv4 = hostIPv4
345-
a.hostIPv6 = hostIPv6
346-
a.guestIPMu.Unlock()
347-
logrus.Infof("Detected the guest has interface %q in same subnet on the host", guestIfnameOnSameSubnetAsHost)
348-
if hostIPv4 != nil {
349-
logrus.Infof("The host IPv4 address on the same subnet as the guest is %q", hostIPv4)
350-
}
351-
if hostIPv6 != nil {
352-
logrus.Infof("The host IPv6 address on the same subnet as the guest is %q", hostIPv6)
353-
}
354338
return nil
355339
}
356340

@@ -359,6 +343,7 @@ func (a *HostAgent) detectGuestIfnameOnSameSubnetAtHost(stdout string) error {
359343
func (a *HostAgent) detectGuestIPAddress(stdout string) error {
360344
a.guestIPMu.RLock()
361345
guestIfnameOnSameSubnetAsHost := a.guestIfnameOnSameSubnetAsHost
346+
hostIfnameOnSameSubnetAsGuest := a.hostIfnameOnSameSubnetAsGuest
362347
a.guestIPMu.RUnlock()
363348
if guestIfnameOnSameSubnetAsHost == "" {
364349
return nil
@@ -375,37 +360,82 @@ func (a *HostAgent) detectGuestIPAddress(stdout string) error {
375360
return fmt.Errorf("failed to parse ip addr output %q: %w", stdout, err)
376361
}
377362
var (
378-
guestIPv4 net.IP
379-
guestIPv6 net.IP
363+
guestIPv4 netip.Addr
364+
guestIPv6 netip.Addr
365+
hostIPv4 netip.Addr
366+
hostIPv6 netip.Addr
380367
)
381368
for _, addr := range addrs {
382369
if addr.IFNAME == guestIfnameOnSameSubnetAsHost {
383370
for _, addr := range addr.ADDRS {
384371
if addr.Scope != "global" {
385372
continue
386373
}
374+
var err error
387375
switch addr.Family {
388376
case "inet":
389-
guestIPv4 = net.ParseIP(addr.Local)
377+
guestIPv4, err = netip.ParseAddr(addr.Local)
378+
if err != nil {
379+
logrus.Warnf("failed to parse guest IPv4 address %q: %v", addr.Local, err)
380+
}
381+
if guestIPv4.Is4In6() {
382+
guestIPv4 = guestIPv4.Unmap()
383+
}
390384
case "inet6":
391-
guestIPv6 = net.ParseIP(addr.Local)
385+
guestIPv6, err = netip.ParseAddr(addr.Local)
386+
if err != nil {
387+
logrus.Warnf("failed to parse guest IPv6 address %q: %v", addr.Local, err)
388+
}
392389
}
393390
}
394391
}
395392
}
396-
if guestIPv4 == nil && guestIPv6 == nil {
393+
if !guestIPv4.IsValid() && !guestIPv6.IsValid() {
397394
logrus.Infof("The interface %q has neither an IPv4 nor an IPv6 address", guestIfnameOnSameSubnetAsHost)
398395
return nil
399396
}
400-
if guestIPv4 != nil {
397+
if guestIPv4.IsValid() {
401398
logrus.Infof("The guest IPv4 address on the interface %q is %q", guestIfnameOnSameSubnetAsHost, guestIPv4)
402399
}
403-
if guestIPv6 != nil {
400+
if guestIPv6.IsValid() {
404401
logrus.Infof("The guest IPv6 address on the interface %q is %q", guestIfnameOnSameSubnetAsHost, guestIPv6)
405402
}
403+
if hostIfnameOnSameSubnetAsGuest != "" {
404+
ifi, err := net.InterfaceByName(hostIfnameOnSameSubnetAsGuest)
405+
if err != nil {
406+
logrus.Warnf("failed to get the interface %q: %v", hostIfnameOnSameSubnetAsGuest, err)
407+
} else if addrs, err := ifi.Addrs(); err != nil {
408+
logrus.Warnf("failed to get addresses of the interface %q: %v", hostIfnameOnSameSubnetAsGuest, err)
409+
} else {
410+
for _, addr := range addrs {
411+
if ipnet := addr.(*net.IPNet); ipnet == nil {
412+
continue
413+
} else if prefix, err := netip.ParsePrefix(ipnet.String()); err != nil {
414+
logrus.Warnf("failed to parse the address %q: %v", ipnet.String(), err)
415+
} else if prefix.Addr().Is4() {
416+
if !hostIPv4.IsValid() && prefix.Contains(guestIPv4) {
417+
hostIPv4 = prefix.Addr()
418+
logrus.Infof("The host IPv4 address on the same subnet as the guest is %q", hostIPv4)
419+
}
420+
} else if prefix.Addr().Is4In6() {
421+
if !hostIPv4.IsValid() && prefix.Contains(netip.AddrFrom16(guestIPv4.As16())) {
422+
hostIPv4 = prefix.Addr().Unmap()
423+
logrus.Infof("The host IPv4 address on the same subnet as the guest is %q", hostIPv4)
424+
}
425+
} else if prefix.Addr().Is6() {
426+
if !hostIPv6.IsValid() && prefix.Contains(guestIPv6) {
427+
hostIPv6 = prefix.Addr()
428+
logrus.Infof("The host IPv6 address on the same subnet as the guest is %q", hostIPv6)
429+
}
430+
}
431+
}
432+
}
433+
}
406434
a.guestIPMu.Lock()
407-
a.guestIPv4 = guestIPv4
408-
a.guestIPv6 = guestIPv6
435+
a.guestIPv4 = net.IP(guestIPv4.AsSlice())
436+
a.guestIPv6 = net.IP(guestIPv6.AsSlice())
437+
a.hostIPv4 = net.IP(hostIPv4.AsSlice())
438+
a.hostIPv6 = net.IP(hostIPv6.AsSlice())
409439
a.guestIPMu.Unlock()
410440
ctx := context.Background()
411441
a.emitGuestIPEvent(ctx, a.GuestIP().String())

0 commit comments

Comments
 (0)