summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/link/wireguard/gtun.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/link/wireguard/gtun.go')
-rw-r--r--pkg/tcpip/link/wireguard/gtun.go135
1 files changed, 135 insertions, 0 deletions
diff --git a/pkg/tcpip/link/wireguard/gtun.go b/pkg/tcpip/link/wireguard/gtun.go
new file mode 100644
index 000000000..d533ca5ba
--- /dev/null
+++ b/pkg/tcpip/link/wireguard/gtun.go
@@ -0,0 +1,135 @@
+package wireguard
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/buffer"
+ "gvisor.dev/gvisor/pkg/tcpip/header"
+ "gvisor.dev/gvisor/pkg/tcpip/link/channel"
+ "gvisor.dev/gvisor/pkg/tcpip/stack"
+ wgtun "golang.zx2c4.com/wireguard/tun"
+)
+
+type WgTun struct {
+ events chan wgtun.Event
+ ch *channel.Endpoint
+ stack *stack.Stack
+ ctx context.Context
+ cancel context.CancelFunc
+}
+
+func (tun *WgTun) File() *os.File {
+ fmt.Println("File")
+ return nil
+}
+
+func (tun *WgTun) Read(buff []byte, offset int) (int, error) {
+ fmt.Println("Read ", len(buff), offset)
+
+ p, ok := tun.ch.ReadContext(tun.ctx)
+ if ok == false {
+ fmt.Println("Read error")
+ return 0, nil // FIXME error
+ }
+ vv := p.Pkt.Data
+ v := vv.ToView()
+ h := p.Pkt.Header.View()
+ fmt.Println("Read packet", vv.Size(), len(v), len(h), h)
+
+ if len(buff) - offset < len(h) + len(v) {
+ fmt.Println("Short buffer")
+ return 0, nil // FIXME error
+ }
+
+ copy(buff[offset:], h)
+ copy(buff[offset+len(h):], v)
+ return len(h)+len(v), nil
+}
+
+func versionToProtocol(version int) tcpip.NetworkProtocolNumber {
+ switch version {
+ case header.IPv4Version: return header.IPv4ProtocolNumber
+ case header.IPv6Version: return header.IPv6ProtocolNumber
+ }
+
+ return 0
+}
+
+func (tun *WgTun) Write(buff []byte, offset int) (int, error) {
+ size := len(buff) - offset
+ fmt.Println("Write ", len(buff), offset, size)
+
+ if size < 1 {
+ return 0, nil // FIXME error
+ }
+
+ buffSlice := buff[offset : offset+size]
+
+ pkt := tcpip.PacketBuffer{
+ Data: buffer.NewViewFromBytes(buffSlice).ToVectorisedView(),
+ }
+ //version := buff[offset] & 0x0f
+ protocol := versionToProtocol(header.IPVersion(buffSlice))
+ netProto := tun.stack.NetworkProtocolInstance(protocol)
+ if netProto == nil {
+ fmt.Println("Write not ok")
+ return 0, nil
+ }
+ src, dst := netProto.ParseAddresses(pkt.Data.First())
+ fmt.Println("Write ", src, dst)
+ // TODO change destination address
+ tun.ch.InjectInbound(protocol, pkt) // FIXME detect protocol number
+
+ return size, nil
+}
+
+func (tun *WgTun) Flush() error {
+ // TODO: can flushing be implemented by buffering and using sendmmsg?
+ fmt.Println("Flush")
+ return nil
+}
+
+func (tun *WgTun) MTU() (int, error) {
+ fmt.Println("MTU")
+ return 1280, nil
+}
+
+func (tun *WgTun) Name() (string, error) {
+ fmt.Println("Name")
+ return "foobar", nil
+}
+
+func (tun *WgTun) Events() chan wgtun.Event {
+ fmt.Println("Events")
+ return tun.events
+}
+
+func (tun *WgTun) Close() error {
+ fmt.Println("Close")
+ // TODO
+// tun.cancel()
+ return nil
+}
+
+func CreateWgTun(s *stack.Stack, ch *channel.Endpoint) (wgtun.Device, error) {
+ size := 16
+ ctx, cancel := context.WithCancel(context.Background())
+ tun := &WgTun{
+ ch: ch,
+ events: make(chan wgtun.Event, size),
+ stack: s,
+ ctx: ctx,
+ cancel: cancel,
+ }
+
+// go func() {
+ fmt.Println("Post event")
+ tun.events <- wgtun.EventUp
+ fmt.Println("Posted event")
+// }()
+
+ return tun, nil
+}