From 77b42aad1f7b95e546eb17640f7981933a5bf999 Mon Sep 17 00:00:00 2001 From: tongsean9807 <105337968+tongsean9807@users.noreply.github.com> Date: Fri, 28 Jun 2024 04:05:43 +0800 Subject: [PATCH] feat(cli): amtinfo command add amt ipaddr and osipaddr (#560) Add os ipaddress to amtinfo command. amtinfo command now show amt ipaddress and os ipaddress. os ipaddress select by mapping to mac address from amt. Resolves: #467 Co-authored-by: Mike --- internal/amt/commands.go | 2 + internal/local/info.go | 90 ++++++++++++++++++++++++++++++++++++- internal/local/info_test.go | 83 ++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 2 deletions(-) diff --git a/internal/amt/commands.go b/internal/amt/commands.go index 79c6bce2..7a0e10f9 100644 --- a/internal/amt/commands.go +++ b/internal/amt/commands.go @@ -42,6 +42,7 @@ type InterfaceSettings struct { DHCPEnabled bool `json:"dhcpEnabled"` DHCPMode string `json:"dhcpMode"` IPAddress string `json:"ipAddress"` //net.IP + OsIPAddress string `json:"osIpAddress"` MACAddress string `json:"macAddress"` } @@ -351,6 +352,7 @@ func (amt AMTCommand) GetLANInterfaceSettings(useWireless bool) (InterfaceSettin settings := InterfaceSettings{ IPAddress: "0.0.0.0", + OsIPAddress: "0.0.0.0", IsEnabled: result.Enabled == 1, DHCPEnabled: result.DhcpEnabled == 1, LinkStatus: "down", diff --git a/internal/local/info.go b/internal/local/info.go index e31f4161..2a23f052 100644 --- a/internal/local/info.go +++ b/internal/local/info.go @@ -6,10 +6,14 @@ package local import ( + "bytes" "encoding/json" + "errors" "fmt" + "net" "os" "rpc/internal/amt" + "rpc/internal/flags" "rpc/pkg/utils" "strconv" "strings" @@ -25,6 +29,63 @@ type PrivateKeyPairReference struct { AssociatedCerts []string } +func GetOSIPAddress(mac_addr string, netEnumerator flags.NetEnumerator) (string, error) { + mac_in_byte := make([]uint8, 6) + + mac_str := strings.Split(mac_addr, ":") + + for i, v := range mac_str { + value, _ := strconv.ParseUint(v, 16, 8) + mac_in_byte[i] = uint8(value) + } + interfaces, err := netEnumerator.Interfaces() + if err != nil { + return "0.0.0.0", errors.New("Failed to get net interfaces") + } + + if bytes.Equal(mac_in_byte, make([]byte, 6)) { + return "0.0.0.0", nil + } + + for _, iface := range interfaces { + if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 { + continue // interface down || loopback interface + } + + hwaddr := iface.HardwareAddr + + if bytes.Equal(hwaddr, mac_in_byte) { + addrs, err := netEnumerator.InterfaceAddrs(&iface) + if err != nil { + return "0.0.0.0", errors.New("Failed to get interface addresses") + } + + for _, addr := range addrs { + var ip net.IP + + switch v := addr.(type) { + case *net.IPNet: + ip = v.IP + case *net.IPAddr: + ip = v.IP + } + + // Check if the IP address is not nil and is an IPv4 address + if ip == nil || ip.IsLoopback() { + continue + } + ip = ip.To4() + if ip == nil { + continue // not an ipv4 address + } + + return ip.String(), nil + } + } + } + return "Not Found", nil +} + func (service *ProvisioningService) DisplayAMTInfo() (err error) { dataStruct := make(map[string]interface{}) cmd := service.amtCommand @@ -158,6 +219,22 @@ func (service *ProvisioningService) DisplayAMTInfo() (err error) { if err != nil { log.Error(err) } + + netEnumerator := flags.NetEnumerator{ + Interfaces: func() ([]net.Interface, error) { + return net.Interfaces() + }, + InterfaceAddrs: func(iface *net.Interface) ([]net.Addr, error) { + return iface.Addrs() + }, + } + + wired_osIpAddress, err := GetOSIPAddress(wired.MACAddress, netEnumerator) + if err != nil { + log.Error(err) + } + wired.OsIPAddress = wired_osIpAddress + dataStruct["wiredAdapter"] = wired if wired.MACAddress != "00:00:00:00:00:00" { @@ -165,7 +242,8 @@ func (service *ProvisioningService) DisplayAMTInfo() (err error) { service.PrintOutput("DHCP Enabled : " + strconv.FormatBool(wired.DHCPEnabled)) service.PrintOutput("DHCP Mode : " + wired.DHCPMode) service.PrintOutput("Link Status : " + wired.LinkStatus) - service.PrintOutput("IP Address : " + wired.IPAddress) + service.PrintOutput("AMT IP Address : " + wired.IPAddress) + service.PrintOutput("OS IP Address : " + wired.OsIPAddress) service.PrintOutput("MAC Address : " + wired.MACAddress) } @@ -173,13 +251,21 @@ func (service *ProvisioningService) DisplayAMTInfo() (err error) { if err != nil { log.Error(err) } + + wireless_osIpAddress, err := GetOSIPAddress(wireless.MACAddress, netEnumerator) + if err != nil { + log.Error(err) + } + wireless.OsIPAddress = wireless_osIpAddress + dataStruct["wirelessAdapter"] = wireless service.PrintOutput("---Wireless Adapter---") service.PrintOutput("DHCP Enabled : " + strconv.FormatBool(wireless.DHCPEnabled)) service.PrintOutput("DHCP Mode : " + wireless.DHCPMode) service.PrintOutput("Link Status : " + wireless.LinkStatus) - service.PrintOutput("IP Address : " + wireless.IPAddress) + service.PrintOutput("AMT IP Address : " + wireless.IPAddress) + service.PrintOutput("OS IP Address : " + wireless.OsIPAddress) service.PrintOutput("MAC Address : " + wireless.MACAddress) } diff --git a/internal/local/info_test.go b/internal/local/info_test.go index 65e6c54f..e354ab42 100644 --- a/internal/local/info_test.go +++ b/internal/local/info_test.go @@ -7,6 +7,7 @@ package local import ( "errors" + "net" "rpc/internal/flags" "rpc/pkg/utils" "testing" @@ -181,3 +182,85 @@ func TestDecodeAMT(t *testing.T) { } } } + +var testNetEnumerator1 = flags.NetEnumerator{ + Interfaces: func() ([]net.Interface, error) { + return []net.Interface{ + { + Index: 0, MTU: 1200, Name: "ethTest01", + HardwareAddr: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, + Flags: 1, + }, + }, nil + }, + InterfaceAddrs: func(i *net.Interface) ([]net.Addr, error) { + if i.Name == "errTest01" { + return nil, errors.New("test message") + } else { + return []net.Addr{ + &net.IPNet{ + IP: net.ParseIP("127.0.0.1"), + Mask: net.CIDRMask(8, 32), + }, + &net.IPNet{ + IP: net.ParseIP("192.168.1.1"), + Mask: net.CIDRMask(24, 32), + }, + }, nil + } + }, +} + +var testNetEnumerator2 = flags.NetEnumerator{ + Interfaces: func() ([]net.Interface, error) { + return []net.Interface{ + { + Index: 0, MTU: 1200, Name: "errTest01", + HardwareAddr: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, + Flags: 1, + }, + }, nil + }, + InterfaceAddrs: func(i *net.Interface) ([]net.Addr, error) { + if i.Name == "errTest01" { + return nil, errors.New("test message") + } else { + return []net.Addr{ + &net.IPNet{ + IP: net.ParseIP("127.0.0.1"), + Mask: net.CIDRMask(8, 32), + }, + &net.IPNet{ + IP: net.ParseIP("192.168.1.1"), + Mask: net.CIDRMask(24, 32), + }, + }, nil + } + }, +} + +func TestGetOSIPAddress(t *testing.T) { + t.Run("Valid MAC address", func(t *testing.T) { + osIpAddress, err := GetOSIPAddress("00:01:02:03:04:05", testNetEnumerator1) + assert.NoError(t, err) + assert.Equal(t, "192.168.1.1", osIpAddress) + }) + + t.Run("Zero MAC address", func(t *testing.T) { + osIpAddress, err := GetOSIPAddress("00:00:00:00:00:00", testNetEnumerator1) + assert.NoError(t, err) + assert.Equal(t, "0.0.0.0", osIpAddress) + }) + + t.Run("net interface fail", func(t *testing.T) { + osIpAddress, err := GetOSIPAddress("00:01:02:03:04:05", testNetEnumerator2) + assert.Equal(t, "0.0.0.0", osIpAddress) + assert.Equal(t, errors.New("Failed to get interface addresses"), err) + }) + + t.Run("no matching mac address to map into os ipaddress", func(t *testing.T) { + osIpAddress, err := GetOSIPAddress("00:11:22:33:44:55", testNetEnumerator1) + assert.Equal(t, "Not Found", osIpAddress) + assert.NoError(t, err) + }) +}