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 {
359343func (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