Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: NICs and their configurations (Windows Only) #160

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
Expand Down
16 changes: 12 additions & 4 deletions net.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,25 @@ 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"`
CanEnable bool `json:"can_enable"`
}

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"`
}
Expand Down
2 changes: 1 addition & 1 deletion net_stub.go
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
143 changes: 143 additions & 0 deletions net_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// 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 wqlNetworkAdapter = "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
}

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
if err := wmi.Query(wqlNetworkAdapter, &win32NetDescriptions); err != nil {
return err
}

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, win32NetConfigurationDescriptions []win32NetworkAdapterConfiguration, win32IP4RouteTableDescriptions []win32IP4RouteTable) []*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{},
}
// 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)
}

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
}

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
}