|
|
@@ -0,0 +1,59 @@
|
|
|
+// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style
|
|
|
+// license that can be found in the LICENSE file.
|
|
|
+
|
|
|
+// Package wgint provides somewhat shady access to wireguard-go
|
|
|
+// internals that don't (yet) have public APIs.
|
|
|
+package wgint
|
|
|
+
|
|
|
+import (
|
|
|
+ "reflect"
|
|
|
+ "sync/atomic"
|
|
|
+ "unsafe"
|
|
|
+
|
|
|
+ "golang.zx2c4.com/wireguard/device"
|
|
|
+)
|
|
|
+
|
|
|
+var (
|
|
|
+ offHandshake = getPeerStatsOffset("lastHandshakeNano")
|
|
|
+ offRxBytes = getPeerStatsOffset("rxBytes")
|
|
|
+ offTxBytes = getPeerStatsOffset("txBytes")
|
|
|
+)
|
|
|
+
|
|
|
+func getPeerStatsOffset(name string) uintptr {
|
|
|
+ peerType := reflect.TypeOf(device.Peer{})
|
|
|
+ sf, ok := peerType.FieldByName("stats")
|
|
|
+ if !ok {
|
|
|
+ panic("no stats field in device.Peer")
|
|
|
+ }
|
|
|
+ if sf.Type.Kind() != reflect.Struct {
|
|
|
+ panic("stats field is not a struct")
|
|
|
+ }
|
|
|
+ base := sf.Offset
|
|
|
+
|
|
|
+ st := sf.Type
|
|
|
+ field, ok := st.FieldByName(name)
|
|
|
+ if !ok {
|
|
|
+ panic("no " + name + " field in device.Peer.stats")
|
|
|
+ }
|
|
|
+ if field.Type.Kind() != reflect.Int64 && field.Type.Kind() != reflect.Uint64 {
|
|
|
+ panic("unexpected kind of " + name + " field in device.Peer.stats")
|
|
|
+ }
|
|
|
+ return base + field.Offset
|
|
|
+}
|
|
|
+
|
|
|
+// PeerLastHandshakeNano returns the last handshake time in nanoseconds since the
|
|
|
+// unix epoch.
|
|
|
+func PeerLastHandshakeNano(peer *device.Peer) int64 {
|
|
|
+ return atomic.LoadInt64((*int64)(unsafe.Add(unsafe.Pointer(peer), offHandshake)))
|
|
|
+}
|
|
|
+
|
|
|
+// PeerRxBytes returns the number of bytes received from this peer.
|
|
|
+func PeerRxBytes(peer *device.Peer) uint64 {
|
|
|
+ return atomic.LoadUint64((*uint64)(unsafe.Add(unsafe.Pointer(peer), offRxBytes)))
|
|
|
+}
|
|
|
+
|
|
|
+// PeerTxBytes returns the number of bytes sent to this peer.
|
|
|
+func PeerTxBytes(peer *device.Peer) uint64 {
|
|
|
+ return atomic.LoadUint64((*uint64)(unsafe.Add(unsafe.Pointer(peer), offTxBytes)))
|
|
|
+}
|