generated from sendnrw/template_golang
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
117 lines
2.2 KiB
Go
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,
|
|
}
|
|
|
|
}
|