diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-12-20 15:35:44 +0100 |
|---|---|---|
| committer | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-12-21 18:28:00 +0100 |
| commit | 6981666c6d8f639a1ff9c09a3bc08769e19928af (patch) | |
| tree | bdb94d76a7fb6a08ef200e9bbbbd5fff1d6b134c /internal/failover/ping.go | |
| parent | 697dfed1f9f5d2916889a81a7a64bd1158caf2d2 (diff) | |
Failover: Initial implementation
Diffstat (limited to 'internal/failover/ping.go')
| -rw-r--r-- | internal/failover/ping.go | 51 |
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 +} |
