feat: improve cross platform ping

- set privileged ping based on run as root
- distinguish between ping errors
This commit is contained in:
Maxi Quoß
2025-03-08 12:39:46 +01:00
parent 59926b8c28
commit 3dcc3fb64b
3 changed files with 51 additions and 9 deletions

View File

@@ -1,18 +1,30 @@
package networking
import (
"fmt"
"net"
"os"
"os/exec"
"runtime"
"strconv"
"syscall"
"time"
"github.com/pocketbase/pocketbase/core"
probing "github.com/prometheus-community/pro-bing"
)
func isNoRouteOrDownError(err error) bool {
opErr, ok := err.(*net.OpError)
if !ok {
return false
}
syscallErr, ok := opErr.Err.(*os.SyscallError)
if !ok {
return false
}
return syscallErr.Err == syscall.EHOSTUNREACH || syscallErr.Err == syscall.EHOSTDOWN
}
func PingDevice(device *core.Record) (bool, error) {
ping_cmd := device.GetString("ping_cmd")
if ping_cmd == "" {
@@ -22,21 +34,26 @@ func PingDevice(device *core.Record) (bool, error) {
}
pinger.Count = 1
pinger.Timeout = 500 * time.Millisecond
privileged, err := strconv.ParseBool(os.Getenv("UPSNAP_PING_PRIVILEGED"))
if err != nil {
privileged = true
privileged := isRoot()
privilegedEnv := os.Getenv("UPSNAP_PING_PRIVILEGED")
if privilegedEnv != "" {
privileged, err = strconv.ParseBool(privilegedEnv)
if err != nil {
privileged = false
}
}
pinger.SetPrivileged(privileged)
err = pinger.Run()
if err != nil {
if isNoRouteOrDownError(err) {
return false, nil
}
return false, err
}
stats := pinger.Statistics()
if stats.PacketLoss > 0 {
return false, fmt.Errorf("packet loss is > 0: %v", stats.PacketLoss)
} else {
return true, nil
}
return stats.PacketLoss == 0, nil
} else {
var shell string
var shell_arg string

View File

@@ -0,0 +1,9 @@
//go:build !windows
package networking
import "os"
func isRoot() bool {
return os.Geteuid() == 0
}

View File

@@ -0,0 +1,16 @@
//go:build windows
package networking
import "golang.org/x/sys/windows"
func isRoot() bool {
var sid *windows.SID
sid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
if err != nil {
return false
}
token := windows.GetCurrentProcessToken()
isAdmin, err := token.IsMember(sid)
return err == nil && isAdmin
}