diff --git a/client/fingerprint/network_default.go b/client/fingerprint/network_default.go index f24479b85..3faa93881 100644 --- a/client/fingerprint/network_default.go +++ b/client/fingerprint/network_default.go @@ -1,4 +1,4 @@ -// +build !linux +// +build !linux,!windows package fingerprint diff --git a/client/fingerprint/network_windows.go b/client/fingerprint/network_windows.go new file mode 100644 index 000000000..8617a65a8 --- /dev/null +++ b/client/fingerprint/network_windows.go @@ -0,0 +1,52 @@ +package fingerprint + +import ( + "fmt" + "os/exec" + "strconv" + "strings" +) + +// linkSpeed returns link speed in Mb/s, or 0 when unable to determine it. +func (f *NetworkFingerprint) linkSpeed(device string) int { + command := fmt.Sprintf("Get-NetAdapter -IncludeHidden | Where name -eq '%s' | Select -ExpandProperty LinkSpeed", device) + path := "powershell.exe" + outBytes, err := exec.Command(path, command).Output() + + if err != nil { + f.logger.Printf("[WARN] fingerprint.network: Error calling %s (%s): %v", path, command, err) + return 0 + } + + output := strings.TrimSpace(string(outBytes)) + + return f.parseLinkSpeed(output) +} + +func (f *NetworkFingerprint) parseLinkSpeed(commandOutput string) int { + args := strings.Split(commandOutput, " ") + if len(args) != 2 { + f.logger.Printf("[WARN] fingerprint.network: Couldn't split LinkSpeed (%s)", commandOutput) + return 0 + } + + unit := strings.Replace(args[1], "\r\n", "", -1) + value, err := strconv.Atoi(args[0]) + if err != nil { + f.logger.Printf("[WARN] fingerprint.network: Unable to parse LinkSpeed value (%s)", commandOutput) + return 0 + } + + switch unit { + case "Mbps": + return value + case "Kbps": + return value / 1000 + case "Gbps": + return value * 1000 + case "bps": + return value / 1000000 + } + + return 0 +} diff --git a/client/fingerprint/network_windows_test.go b/client/fingerprint/network_windows_test.go new file mode 100644 index 000000000..0cc8acfdf --- /dev/null +++ b/client/fingerprint/network_windows_test.go @@ -0,0 +1,30 @@ +package fingerprint + +import "testing" + +func TestNetworkFingerPrint_linkspeed_parse(t *testing.T) { + f := &NetworkFingerprint{logger: testLogger(), interfaceDetector: &DefaultNetworkInterfaceDetector{}} + + var outputTests = []struct { + in string + out int + }{ + {"10 Mbps", 10}, + {"2 bps", 0}, + {"1 Gbps", 1000}, + {"2Mbps", 0}, + {"1000 Kbps", 1}, + {"1 Kbps", 0}, + {"0 Mbps", 0}, + {"2 2 Mbps", 0}, + {"a Mbps", 0}, + {"1 Tbps", 0}, + } + + for _, ot := range outputTests { + out := f.parseLinkSpeed(ot.in) + if out != ot.out { + t.Errorf("parseLinkSpeed(%s) => %d, should be %d", ot.in, out, ot.out) + } + } +}