Skip to content

Commit 29db5b5

Browse files
committed
pkg/hostagent: Set LocalAddr to net.Dialer in DialContextToGuestIP()
Signed-off-by: Norio Nomura <[email protected]>
1 parent fcf679f commit 29db5b5

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

pkg/hostagent/hostagent.go

Lines changed: 27 additions & 7 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+
// Host IP address on the same subnet as the guest.
93+
hostIPv4 net.IP
94+
hostIPv6 net.IP
9295
}
9396

9497
type options struct {
@@ -542,6 +545,14 @@ func (a *HostAgent) GuestIPv6() net.IP {
542545
return a.guestIPv6
543546
}
544547

548+
// HostIPs returns the host's IP addresses on the same subnet as the guest.
549+
// It returns nil if the guest is not reachable by a direct IP.
550+
func (a *HostAgent) HostIPs() (ipv4, ipv6 net.IP) {
551+
a.guestIPMu.RLock()
552+
defer a.guestIPMu.RUnlock()
553+
return a.hostIPv4, a.hostIPv6
554+
}
555+
545556
func (a *HostAgent) Info(_ context.Context) (*hostagentapi.Info, error) {
546557
guestIP := a.GuestIP()
547558
info := &hostagentapi.Info{
@@ -800,7 +811,7 @@ func (a *HostAgent) watchGuestAgentEvents(ctx context.Context) {
800811
func (a *HostAgent) addStaticPortForwardsFromList(ctx context.Context, staticPortForwards []limatype.PortForward) {
801812
// Since port forwarding to the guest IP directly does not require guest agent,
802813
// we can support static port forwarding if DialContextToGuestIP() returns non-nil.
803-
dialContext := DialContextToGuestIP(a.GuestIP())
814+
dialContext := a.DialContextToGuestIP(a.GuestIP())
804815
sshAddress, sshPort := a.sshAddressPort()
805816
for _, rule := range staticPortForwards {
806817
if rule.GuestSocket == "" {
@@ -932,15 +943,15 @@ func (a *HostAgent) processGuestAgentEvents(ctx context.Context, client *guestag
932943
} else if ip := net.ParseIP(host); ip.IsUnspecified() || ip.Equal(guestIPv4) || ip.Equal(guestIPv6) {
933944
if ip.To4() != nil {
934945
if guestIPv4 != nil {
935-
return DialContextToGuestIP(guestIPv4)(ctx, network, guestAddress)
946+
return a.DialContextToGuestIP(guestIPv4)(ctx, network, guestAddress)
936947
} else if guestIPv4 = a.GuestIPv6().To4(); guestIPv4 != nil {
937-
return DialContextToGuestIP(guestIPv4)(ctx, network, guestAddress)
948+
return a.DialContextToGuestIP(guestIPv4)(ctx, network, guestAddress)
938949
}
939950
} else if ip.To16() != nil {
940951
if guestIPv6 != nil {
941-
return DialContextToGuestIP(guestIPv6)(ctx, network, guestAddress)
952+
return a.DialContextToGuestIP(guestIPv6)(ctx, network, guestAddress)
942953
} else if guestIPv6 = a.GuestIPv4().To16(); guestIPv6 != nil {
943-
return DialContextToGuestIP(guestIPv6)(ctx, network, guestAddress)
954+
return a.DialContextToGuestIP(guestIPv6)(ctx, network, guestAddress)
944955
}
945956
}
946957
// If we reach here, it means we couldn't find a suitable guest IP
@@ -962,12 +973,21 @@ func (a *HostAgent) processGuestAgentEvents(ctx context.Context, client *guestag
962973

963974
// DialContextToGuestIP returns a DialContext function that connects to the guest IP directly.
964975
// If the guest IP is not known, it returns nil.
965-
func DialContextToGuestIP(guestIP net.IP) func(ctx context.Context, network, address string) (net.Conn, error) {
976+
func (a *HostAgent) DialContextToGuestIP(guestIP net.IP) func(ctx context.Context, network, address string) (net.Conn, error) {
966977
if guestIP == nil {
967978
return nil
968979
}
980+
var sourceIP net.IP
981+
hostIPv4, hostIPv6 := a.HostIPs()
982+
if hostIPv4 != nil && guestIP.To4() != nil {
983+
sourceIP = hostIPv4
984+
} else if hostIPv6 != nil && guestIP.To16() != nil {
985+
sourceIP = hostIPv6
986+
} else {
987+
return nil
988+
}
969989
return func(ctx context.Context, network, address string) (net.Conn, error) {
970-
var d net.Dialer
990+
d := net.Dialer{LocalAddr: &net.TCPAddr{IP: sourceIP}}
971991
_, port, err := net.SplitHostPort(address)
972992
if err != nil {
973993
return nil, err

pkg/hostagent/requirements.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,19 +321,36 @@ func (a *HostAgent) detectGuestIfnameOnSameSubnetAtHost(stdout string) error {
321321
if err != nil {
322322
return fmt.Errorf("failed to get network interfaces: %w", err)
323323
}
324+
var (
325+
guestIfnameOnSameSubnetAsHost string
326+
hostIPv4 net.IP
327+
hostIPv6 net.IP
328+
)
324329
for _, neighbor := range neighbors {
325330
for _, ifi := range interfaces {
326331
if ifi.HardwareAddr.String() != neighbor.LLADDR {
327332
continue
328333
}
329-
a.guestIPMu.Lock()
330-
a.guestIfnameOnSameSubnetAsHost = neighbor.DEV
331-
a.guestIPMu.Unlock()
332-
logrus.Infof("Detected the guest has interface %q in same subnet on the host", neighbor.DEV)
333-
return nil
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+
}
334340
}
335341
}
336-
logrus.Info("The guest does not have interface in same subnet on the host")
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+
}
337354
return nil
338355
}
339356

0 commit comments

Comments
 (0)