From 4eb761a8795b8aa6c371dca53968482c162bae3f Mon Sep 17 00:00:00 2001 From: Riccardo Re Date: Thu, 6 Feb 2020 17:01:52 +0100 Subject: [PATCH 1/4] Windows support: net Added partial windows support to net --- go.mod | 2 ++ go.sum | 4 ++++ net_stub.go | 2 +- net_windows.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 net_windows.go diff --git a/go.mod b/go.mod index 3e2bc9de..f3d0e255 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,9 @@ module github.com/jaypipes/ghw go 1.12 require ( + github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d github.com/ghodss/yaml v1.0.0 + github.com/go-ole/go-ole v1.2.4 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jaypipes/pcidb v0.5.0 github.com/pkg/errors v0.8.0 diff --git a/go.sum b/go.sum index c37c2768..8833173f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= +github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= +github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaypipes/pcidb v0.5.0 h1:4W5gZ+G7QxydevI8/MmmKdnIPJpURqJ2JNXTzfLxF5c= diff --git a/net_stub.go b/net_stub.go index f5e5f2f9..6c2365fd 100644 --- a/net_stub.go +++ b/net_stub.go @@ -1,4 +1,4 @@ -// +build !linux +// +build !linux, !windows // Use and distribution licensed under the Apache license version 2. // // See the COPYING file in the root project directory for full text. diff --git a/net_windows.go b/net_windows.go new file mode 100644 index 00000000..bb922531 --- /dev/null +++ b/net_windows.go @@ -0,0 +1,65 @@ +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package ghw + +import ( + "strings" + + "github.com/StackExchange/wmi" +) + +const wqlProduct = "SELECT Description, DeviceID, Index, InterfaceIndex, MACAddress, Manufacturer, Name, NetConnectionID, ProductName, ServiceName FROM Win32_NetworkAdapter" + +type win32NetworkAdapter struct { + Description string + DeviceID string + Index uint32 + InterfaceIndex uint32 + MACAddress string + Manufacturer string + Name string + NetConnectionID string + ProductName string + ServiceName string +} + +func (ctx *context) netFillInfo(info *NetworkInfo) error { + // Getting info from WMI + var win32NetDescriptions []win32NetworkAdapter + if err := wmi.Query(wqlProduct, &win32NetDescriptions); err != nil { + return err + } + + info.NICs = ctx.nics(win32NetDescriptions) + return nil +} + +func (ctx *context) nics(win32NetDescriptions []win32NetworkAdapter) []*NIC { + // Converting into standard structures + nics := make([]*NIC, 0) + for _, nicDescription := range win32NetDescriptions { + nic := &NIC{ + Name: ctx.netDeviceName(nicDescription), + MacAddress: nicDescription.MACAddress, + IsVirtual: false, + Capabilities: []*NICCapability{}, + } + // Appenging NIC to NICs + nics = append(nics, nic) + } + + return nics +} + +func (ctx *context) netDeviceName(description win32NetworkAdapter) string { + var name string + if strings.TrimSpace(description.NetConnectionID) != "" { + name = description.NetConnectionID + " - " + description.Description + } else { + name = description.Description + } + return name +} From daaaa7716340d394350560f4a08a4a6ca2996891 Mon Sep 17 00:00:00 2001 From: Riccardo Re Date: Thu, 6 Feb 2020 18:24:11 +0100 Subject: [PATCH 2/4] Typo --- net_stub.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net_stub.go b/net_stub.go index 6c2365fd..a2f75c0f 100644 --- a/net_stub.go +++ b/net_stub.go @@ -1,4 +1,4 @@ -// +build !linux, !windows +// +build !linux,!windows // Use and distribution licensed under the Apache license version 2. // // See the COPYING file in the root project directory for full text. From 4feedd0612d286afb2ac33e8d43e09a9314022c1 Mon Sep 17 00:00:00 2001 From: Riccardo Re Date: Fri, 7 Feb 2020 08:20:47 +0100 Subject: [PATCH 3/4] Wrong copy&paste --- net_windows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net_windows.go b/net_windows.go index bb922531..1141a7d2 100644 --- a/net_windows.go +++ b/net_windows.go @@ -11,7 +11,7 @@ import ( "github.com/StackExchange/wmi" ) -const wqlProduct = "SELECT Description, DeviceID, Index, InterfaceIndex, MACAddress, Manufacturer, Name, NetConnectionID, ProductName, ServiceName FROM Win32_NetworkAdapter" +const wqlNetworkAdapter = "SELECT Description, DeviceID, Index, InterfaceIndex, MACAddress, Manufacturer, Name, NetConnectionID, ProductName, ServiceName FROM Win32_NetworkAdapter" type win32NetworkAdapter struct { Description string @@ -29,7 +29,7 @@ type win32NetworkAdapter struct { func (ctx *context) netFillInfo(info *NetworkInfo) error { // Getting info from WMI var win32NetDescriptions []win32NetworkAdapter - if err := wmi.Query(wqlProduct, &win32NetDescriptions); err != nil { + if err := wmi.Query(wqlNetworkAdapter, &win32NetDescriptions); err != nil { return err } From 21c230a0f1ffe56e259c90eea57ff12c958c09fb Mon Sep 17 00:00:00 2001 From: Riccardo Re Date: Fri, 7 Feb 2020 08:29:25 +0100 Subject: [PATCH 4/4] Feature: NICs and their configurations (Windows Only) When collecting HW informations about NICs it's also very usefull to know their current configurations. Here a quick example based on my "Windows support: net" https://github.com/jaypipes/ghw/pull/157 --- net.go | 16 +++++++--- net_windows.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/net.go b/net.go index 3c66be7e..fbdd5e4a 100644 --- a/net.go +++ b/net.go @@ -10,6 +10,13 @@ import ( "fmt" ) +type NICConfiguration struct { + DHCPenabled bool `json:"dhcp_enabled"` + Gateway string `json:"gateway"` + IPv4 string `json:"ipv4"` + IPv6 string `json:"ipv6"` +} + type NICCapability struct { Name string `json:"name"` IsEnabled bool `json:"is_enabled"` @@ -17,10 +24,11 @@ type NICCapability struct { } type NIC struct { - Name string `json:"name"` - MacAddress string `json:"mac_address"` - IsVirtual bool `json:"is_virtual"` - Capabilities []*NICCapability `json:"capabilities"` + Name string `json:"name"` + MacAddress string `json:"mac_address"` + IsVirtual bool `json:"is_virtual"` + Capabilities []*NICCapability `json:"capabilities"` + Configurations []*NICConfiguration `json:"configurations"` // TODO(jaypipes): Add PCI field for accessing PCI device information // PCI *PCIDevice `json:"pci"` } diff --git a/net_windows.go b/net_windows.go index 1141a7d2..170ba07c 100644 --- a/net_windows.go +++ b/net_windows.go @@ -26,6 +26,39 @@ type win32NetworkAdapter struct { ServiceName string } +const wqlNetworkAdapterCnofiguration = "SELECT Caption, Description, DefaultIPGateway, DHCPEnabled, Index, InterfaceIndex, IPAddress FROM Win32_NetworkAdapterConfiguration" + +type win32NetworkAdapterConfiguration struct { + Caption string + Description string + DefaultIPGateway []string + DHCPEnabled bool + Index uint32 + InterfaceIndex uint32 + IPAddress []string +} + +const wqlIP4RouteTable = "SELECT Caption, Description, Destination, Information, InterfaceIndex, Mask, Metric1, Metric2, Metric3, Metric4, Metric5, Name, NextHop, Protocol, Status, Type FROM Win32_IP4RouteTable" + +type win32IP4RouteTable struct { + Caption string + Description string + Destination string + Information string + InterfaceIndex int32 + Mask string + Metric1 int32 + Metric2 int32 + Metric3 int32 + Metric4 int32 + Metric5 int32 + Name string + NextHop string + Protocol uint32 + Status string + Type uint32 +} + func (ctx *context) netFillInfo(info *NetworkInfo) error { // Getting info from WMI var win32NetDescriptions []win32NetworkAdapter @@ -33,11 +66,21 @@ func (ctx *context) netFillInfo(info *NetworkInfo) error { return err } - info.NICs = ctx.nics(win32NetDescriptions) + var win32NetConfigurationDescriptions []win32NetworkAdapterConfiguration + if err := wmi.Query(wqlNetworkAdapterCnofiguration, &win32NetConfigurationDescriptions); err != nil { + return err + } + + var win32IP4RouteTableDescriptions []win32IP4RouteTable + if err := wmi.Query(wqlIP4RouteTable, &win32IP4RouteTableDescriptions); err != nil { + return err + } + + info.NICs = ctx.nics(win32NetDescriptions, win32NetConfigurationDescriptions, win32IP4RouteTableDescriptions) return nil } -func (ctx *context) nics(win32NetDescriptions []win32NetworkAdapter) []*NIC { +func (ctx *context) nics(win32NetDescriptions []win32NetworkAdapter, win32NetConfigurationDescriptions []win32NetworkAdapterConfiguration, win32IP4RouteTableDescriptions []win32IP4RouteTable) []*NIC { // Converting into standard structures nics := make([]*NIC, 0) for _, nicDescription := range win32NetDescriptions { @@ -47,6 +90,29 @@ func (ctx *context) nics(win32NetDescriptions []win32NetworkAdapter) []*NIC { IsVirtual: false, Capabilities: []*NICCapability{}, } + // Building NIC configurations + for _, configDescription := range win32NetConfigurationDescriptions { + // Looking for configurations + if nicDescription.InterfaceIndex == configDescription.InterfaceIndex { + ipv4, ipv6 := ctx.netConfigIP(configDescription.IPAddress) + var configuration = &NICConfiguration{ + DHCPenabled: configDescription.DHCPEnabled, + IPv4: ipv4, + IPv6: ipv6, + } + // Looking for gateway + for _, routeDescription := range win32IP4RouteTableDescriptions { + if nicDescription.InterfaceIndex == uint32(routeDescription.InterfaceIndex) { + if routeDescription.Destination == "0.0.0.0" && routeDescription.Mask == "0.0.0.0" { + configuration.Gateway = routeDescription.NextHop + break + } + } + } + // Appending configuration to NIC configurations + nic.Configurations = append(nic.Configurations, configuration) + } + } // Appenging NIC to NICs nics = append(nics, nic) } @@ -63,3 +129,15 @@ func (ctx *context) netDeviceName(description win32NetworkAdapter) string { } return name } + +func (ctx *context) netConfigIP(IPs []string) (string, string) { + var IPv4 string + var IPv6 string + if len(IPs) > 0 { + IPv4 = IPs[0] + } + if len(IPs) > 1 { + IPv6 = IPs[1] + } + return IPv4, IPv6 +}