Files
prom-ping/pinger.go
jbergner 75676069ce
Some checks failed
build-binaries / build (, amd64, linux) (push) Has been skipped
build-binaries / build (, arm, 7, linux) (push) Has been skipped
build-binaries / build (, arm64, linux) (push) Has been skipped
build-binaries / build (.exe, amd64, windows) (push) Has been skipped
build-binaries / release (push) Has been skipped
build-binaries / publish-agent (push) Has been skipped
release-tag / release-image (push) Has been cancelled
init
2025-10-31 06:50:26 +01:00

117 lines
2.2 KiB
Go

package main
import (
"errors"
"net"
"time"
"github.com/miekg/dns"
probing "github.com/prometheus-community/pro-bing"
)
type PingResult struct {
RTT time.Duration
Alive bool
Err error
IP string
}
type PingOptions struct {
Timeout time.Duration
Size int
DisableIPv6 bool
DNSServer string
}
func resolveWithCustomDNS(server, host string) (string, error) {
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(host), dns.TypeA)
resp, _, err := c.Exchange(m, server)
if err != nil {
return "", err
}
for _, ans := range resp.Answer {
if a, ok := ans.(*dns.A); ok {
return a.A.String(), nil
}
}
return "", errors.New("no A record found")
}
func resolveHost(host, dnsServer string, disableIPv6 bool) (string, error) {
if ip := net.ParseIP(host); ip != nil {
return host, nil
}
if dnsServer != "" {
if _, _, err := net.SplitHostPort(dnsServer); err != nil {
dnsServer = net.JoinHostPort(dnsServer, "53")
}
return resolveWithCustomDNS(dnsServer, host)
}
if disableIPv6 {
ips, err := net.LookupIP(host)
if err != nil {
return "", err
}
for _, ip := range ips {
if ip.To4() != nil {
return ip.String(), nil
}
}
return "", errors.New("no IPv4 address found")
}
ip, err := net.ResolveIPAddr("ip", host)
if err != nil {
return "", err
}
return ip.IP.String(), nil
}
func doPing(host string, opts PingOptions) PingResult {
ip, err := resolveHost(host, opts.DNSServer, opts.DisableIPv6)
if err != nil {
return PingResult{Alive: false, Err: err}
}
pinger, err := probing.NewPinger(ip)
if err != nil {
return PingResult{Alive: false, Err: err, IP: ip}
}
if opts.DisableIPv6 {
pinger.SetNetwork("ip4")
}
pinger.Count = 1
pinger.Timeout = opts.Timeout
pinger.Size = opts.Size
// falls du im Container kein CAP_NET_RAW gibst:
pinger.SetPrivileged(false) // oder aus Config
// wenn du CAP_NET_RAW vergibst:
// pinger.SetPrivileged(true)
if err := pinger.Run(); err != nil {
return PingResult{Alive: false, Err: err, IP: ip}
}
stats := pinger.Statistics()
if stats.PacketsRecv < 1 {
return PingResult{Alive: false, Err: errors.New("no reply"), IP: ip}
}
return PingResult{
RTT: stats.AvgRtt,
Alive: true,
IP: ip,
}
}