diff options
Diffstat (limited to 'pkg/tcpip/link/wireguard/gtun.go')
-rw-r--r-- | pkg/tcpip/link/wireguard/gtun.go | 135 |
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 +} |