Skip to content

Commit c4ffa31

Browse files
committed
Support get IPs for both guestagent and plain mode
Signed-off-by: Songpon Srisawai <[email protected]>
1 parent 7a6078c commit c4ffa31

File tree

8 files changed

+290
-10
lines changed

8 files changed

+290
-10
lines changed

pkg/guestagent/api/client/client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,11 @@ func (c *GuestAgentClient) Tunnel(ctx context.Context) (api.GuestService_TunnelC
7676
}
7777
return stream, nil
7878
}
79+
80+
func (c *GuestAgentClient) IPv4(ctx context.Context) (*api.CommandOutput, error) {
81+
return c.cli.GetIPv4(ctx, &emptypb.Empty{})
82+
}
83+
84+
func (c *GuestAgentClient) IPv6(ctx context.Context) (*api.CommandOutput, error) {
85+
return c.cli.GetIPv6(ctx, &emptypb.Empty{})
86+
}

pkg/guestagent/api/guestservice.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ service GuestService {
1111
rpc PostInotify(stream Inotify) returns (google.protobuf.Empty);
1212

1313
rpc Tunnel(stream TunnelMessage) returns (stream TunnelMessage);
14+
rpc GetIPv4(google.protobuf.Empty) returns (CommandOutput);
15+
rpc GetIPv6(google.protobuf.Empty) returns (CommandOutput);
1416
}
1517

1618
message Info {
@@ -30,6 +32,11 @@ message IPPort {
3032
int32 port = 3;
3133
}
3234

35+
message CommandOutput {
36+
bool is_json = 1;
37+
bytes payload = 2;
38+
}
39+
3340
message Inotify {
3441
string mount_path = 1;
3542
google.protobuf.Timestamp time = 2;

pkg/guestagent/api/server/server.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,11 @@ func (s *GuestServer) PostInotify(server api.GuestService_PostInotifyServer) err
5656
func (s *GuestServer) Tunnel(stream api.GuestService_TunnelServer) error {
5757
return s.TunnelS.Start(stream)
5858
}
59+
60+
func (s *GuestServer) GetIPv4(ctx context.Context, _ *emptypb.Empty) (*api.CommandOutput, error) {
61+
return s.Agent.IPv4(ctx)
62+
}
63+
64+
func (s *GuestServer) GetIPv6(ctx context.Context, _ *emptypb.Empty) (*api.CommandOutput, error) {
65+
return s.Agent.IPv6(ctx)
66+
}

pkg/guestagent/guestagent.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ type Agent interface {
1414
Events(ctx context.Context, ch chan *api.Event)
1515
LocalPorts(ctx context.Context) ([]*api.IPPort, error)
1616
HandleInotify(event *api.Inotify)
17+
IPv4(ctx context.Context) (*api.CommandOutput, error)
18+
IPv6(ctx context.Context) (*api.CommandOutput, error)
19+
}
20+
21+
type RouteEntry struct {
22+
Dev string `json:"dev"`
1723
}

pkg/guestagent/guestagent_linux.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ package guestagent
55

66
import (
77
"context"
8+
"encoding/json"
89
"errors"
910
"os"
11+
"os/exec"
1012
"reflect"
1113
"sync"
1214
"syscall"
@@ -186,6 +188,7 @@ func (a *agent) collectEvent(ctx context.Context, st eventState) (*api.Event, ev
186188
}
187189
ev.AddedLocalPorts, ev.RemovedLocalPorts = comparePorts(st.ports, newSt.ports)
188190
ev.Time = timestamppb.Now()
191+
189192
return ev, newSt
190193
}
191194

@@ -368,3 +371,77 @@ func (a *agent) HandleInotify(event *api.Inotify) {
368371
}
369372
}
370373
}
374+
375+
func (a *agent) IPv4(ctx context.Context) (*api.CommandOutput, error) {
376+
return a.getIPAddress(ctx, "4")
377+
}
378+
379+
func (a *agent) IPv6(ctx context.Context) (*api.CommandOutput, error) {
380+
return a.getIPAddress(ctx, "6")
381+
}
382+
383+
// getIPAddress performs two steps:
384+
// (1) Identifies the default interface using "ip route show default".
385+
// (2) Retrieves interface details for IPv4 or IPv6.
386+
// Returns nil if no default interface is found.
387+
func (a *agent) getIPAddress(_ context.Context, ipVersion string) (*api.CommandOutput, error) {
388+
// Get default interface
389+
iface, err := getDefaultInterface(ipVersion)
390+
if err != nil {
391+
logrus.Errorf("Error getting default interface: %v", err)
392+
}
393+
394+
// Get Interface info
395+
output, err := getInterfaceInfo(ipVersion, iface)
396+
if err != nil {
397+
logrus.Errorf("Error getting interface info for %s: %v", iface, err)
398+
}
399+
400+
return &api.CommandOutput{
401+
IsJson: true,
402+
Payload: output,
403+
}, err
404+
}
405+
406+
// getDefaultInterface fetches the default interface for IPv4 or IPv6.
407+
func getDefaultInterface(ipVersion string) (string, error) {
408+
args := []string{"-j", "route", "show", "default"}
409+
if ipVersion == "6" {
410+
args = append([]string{"-6"}, args...)
411+
} else {
412+
args = append([]string{"-4"}, args...)
413+
}
414+
415+
output, err := exec.Command("ip", args...).Output()
416+
if err != nil {
417+
return "", errors.New("failed to run `ip route show default`")
418+
}
419+
420+
var routes []RouteEntry
421+
if err := json.Unmarshal(output, &routes); err != nil {
422+
return "", errors.New("failed to unmarshal route JSON")
423+
}
424+
425+
// return nil if no default interface
426+
if len(routes) == 0 || routes[0].Dev == "" {
427+
return "", nil
428+
}
429+
430+
return routes[0].Dev, nil
431+
}
432+
433+
// getInterfaceInfo fetches the interface information for IPv4 or IPv6.
434+
func getInterfaceInfo(ipVersion, iface string) ([]byte, error) {
435+
// No default route found
436+
if iface == "" {
437+
return nil, nil
438+
}
439+
440+
args := []string{"-j", "address", "show", "dev", iface}
441+
if ipVersion == "6" {
442+
args = append([]string{"-6"}, args...)
443+
} else {
444+
args = append([]string{"-4"}, args...)
445+
}
446+
return exec.Command("ip", args...).Output()
447+
}

pkg/hostagent/api/api.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
package api
55

66
type Info struct {
7-
SSHLocalPort int `json:"sshLocalPort,omitempty"`
7+
SSHLocalPort int `json:"sshLocalPort,omitempty"`
8+
GuestIPv4Address string `json:"guestIPv4Address,omitempty"`
9+
GuestIPv6Address string `json:"guestIPv6Address,omitempty"`
810
}

0 commit comments

Comments
 (0)