This commit is contained in:
jdl
2026-06-07 18:12:44 +02:00
parent cad200b9cc
commit b8344a20b9
37 changed files with 568 additions and 981 deletions

View File

@@ -11,14 +11,14 @@ import (
const (
version = 1
Size = 59 // 1 version + 8 ID + 8 PingTS + 6 SrcV4 + 18 SrcV6 + 18 Dst
Size = 51 // 1 version + 8 PingTS + 6 SrcV4 + 18 SrcV6 + 18 Dst
)
// Ping is the single control packet type exchanged between VPN peers.
//
// In each peer pair, the peer with the lower VPN IP is the client: it sets ID
// and PingTS and sends pings on a timer. The server echoes ID and PingTS back
// in its response, allowing the client to compute RTT = now - PingTS.
// In each peer pair, the peer with the lower VPN IP is the client: it sets
// PingTS and sends pings on a timer. The server echoes PingTS back in its
// response, allowing the client to compute RTT = now - PingTS.
//
// Both client and server populate SrcV4, SrcV6, and Dst on every packet so
// endpoint information flows in both directions.
@@ -27,50 +27,47 @@ const (
// WireGuard handshake source. Zero if the sender has not observed a handshake
// from the recipient.
type Ping struct {
ID int64 // Client ping ID.
PingTS int64 // Client ping send time in nanoseconds.
SrcV4 netip.AddrPort // Sender's discovered IPv4 address and port.
SrcV6 netip.AddrPort // Sender's discovered IPv6 address and port.
Dst netip.AddrPort
}
// Marshal encodes p into a fixed-size 59-byte array.
// Marshal encodes p into a fixed-size 51-byte array.
func (p Ping) Marshal() [Size]byte {
var buf [Size]byte
buf[0] = version
binary.BigEndian.PutUint64(buf[1:9], uint64(p.ID))
binary.BigEndian.PutUint64(buf[9:17], uint64(p.PingTS))
binary.BigEndian.PutUint64(buf[1:9], uint64(p.PingTS))
if p.SrcV4.IsValid() {
a4 := p.SrcV4.Addr().As4()
copy(buf[17:21], a4[:])
binary.BigEndian.PutUint16(buf[21:23], p.SrcV4.Port())
copy(buf[9:13], a4[:])
binary.BigEndian.PutUint16(buf[13:15], p.SrcV4.Port())
}
a16 := p.SrcV6.Addr().As16()
copy(buf[23:39], a16[:])
binary.BigEndian.PutUint16(buf[39:41], p.SrcV6.Port())
copy(buf[15:31], a16[:])
binary.BigEndian.PutUint16(buf[31:33], p.SrcV6.Port())
a16 = p.Dst.Addr().As16()
copy(buf[41:57], a16[:])
binary.BigEndian.PutUint16(buf[57:59], p.Dst.Port())
copy(buf[33:49], a16[:])
binary.BigEndian.PutUint16(buf[49:51], p.Dst.Port())
return buf
}
// Unmarshal decodes a Ping from a fixed-size 59-byte array.
// Unmarshal decodes a Ping from a fixed-size 51-byte array.
func Unmarshal(buf [Size]byte) (Ping, error) {
if buf[0] != version {
return Ping{}, fmt.Errorf("unknown ping version %d", buf[0])
}
p := Ping{
ID: int64(binary.BigEndian.Uint64(buf[1:9])),
PingTS: int64(binary.BigEndian.Uint64(buf[9:17])),
PingTS: int64(binary.BigEndian.Uint64(buf[1:9])),
}
if addr := netip.AddrFrom4([4]byte(buf[17:21])); !addr.IsUnspecified() {
p.SrcV4 = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[21:23]))
if addr := netip.AddrFrom4([4]byte(buf[9:13])); !addr.IsUnspecified() {
p.SrcV4 = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[13:15]))
}
if addr := netip.AddrFrom16([16]byte(buf[23:39])); !addr.IsUnspecified() {
p.SrcV6 = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[39:41]))
if addr := netip.AddrFrom16([16]byte(buf[15:31])); !addr.IsUnspecified() {
p.SrcV6 = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[31:33]))
}
if addr := netip.AddrFrom16([16]byte(buf[41:57])).Unmap(); !addr.IsUnspecified() {
p.Dst = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[57:59]))
if addr := netip.AddrFrom16([16]byte(buf[33:49])).Unmap(); !addr.IsUnspecified() {
p.Dst = netip.AddrPortFrom(addr, binary.BigEndian.Uint16(buf[49:51]))
}
return p, nil
}