summaryrefslogtreecommitdiff
path: root/internal/failover/ping.go
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-12-20 15:35:44 +0100
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-12-21 18:28:00 +0100
commit6981666c6d8f639a1ff9c09a3bc08769e19928af (patch)
treebdb94d76a7fb6a08ef200e9bbbbd5fff1d6b134c /internal/failover/ping.go
parent697dfed1f9f5d2916889a81a7a64bd1158caf2d2 (diff)
Failover: Initial implementation
Diffstat (limited to 'internal/failover/ping.go')
-rw-r--r--internal/failover/ping.go51
1 files changed, 51 insertions, 0 deletions
diff --git a/internal/failover/ping.go b/internal/failover/ping.go
new file mode 100644
index 0000000..2ffedd4
--- /dev/null
+++ b/internal/failover/ping.go
@@ -0,0 +1,51 @@
+package failover
+
+import (
+ "fmt"
+ "net"
+ "os"
+
+ "golang.org/x/net/icmp"
+ "golang.org/x/net/ipv4"
+
+ "github.com/go-errors/errors"
+)
+
+// mtuOverhead defines the total MTU overhead for an ICMP ECHO message: 20 bytes IP header + 8 bytes ICMP header
+var mtuOverhead = 28
+
+type Pinger struct {
+ listener net.PacketConn
+ buffer []byte
+}
+
+func NewPinger(size int) (*Pinger, error) {
+ l, err := icmp.ListenPacket("udp4", "0.0.0.0")
+ if err != nil {
+ return nil, errors.WrapPrefix(err, "failed creating ping", 0)
+ }
+ return &Pinger{listener: l, buffer: make([]byte, size-mtuOverhead)}, nil
+}
+
+func (p Pinger) Send(gateway string, seq int) error {
+ errorMessage := fmt.Sprintf("failed sending ping, seq %d", seq)
+ // Make a new ICMP message
+ m := icmp.Message{
+ Type: ipv4.ICMPTypeEcho, Code: 0,
+ Body: &icmp.Echo{
+ ID: os.Getpid() & 0xffff, Seq: seq,
+ Data: p.buffer,
+ },
+ }
+ // Marshal the message to bytes
+ b, err := m.Marshal(nil)
+ if err != nil {
+ return errors.WrapPrefix(err, errorMessage, 0)
+ }
+ // And send it to the gateway IP!
+ _, err = p.listener.WriteTo(b, &net.UDPAddr{IP: net.ParseIP(gateway)})
+ if err != nil {
+ return errors.WrapPrefix(err, errorMessage, 0)
+ }
+ return nil
+}