//go:build with_gvisor && windows package tun import ( "gvisor.dev/gvisor/pkg/bufferv2" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/stack" ) var _ GVisorTun = (*NativeTun)(nil) func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) { return &WintunEndpoint{tun: t}, nil } var _ stack.LinkEndpoint = (*WintunEndpoint)(nil) type WintunEndpoint struct { tun *NativeTun dispatcher stack.NetworkDispatcher } func (e *WintunEndpoint) MTU() uint32 { return e.tun.options.MTU } func (e *WintunEndpoint) MaxHeaderLength() uint16 { return 0 } func (e *WintunEndpoint) LinkAddress() tcpip.LinkAddress { return "" } func (e *WintunEndpoint) Capabilities() stack.LinkEndpointCapabilities { return stack.CapabilityNone } func (e *WintunEndpoint) Attach(dispatcher stack.NetworkDispatcher) { if dispatcher == nil && e.dispatcher != nil { e.dispatcher = nil return } if dispatcher != nil && e.dispatcher == nil { e.dispatcher = dispatcher go e.dispatchLoop() } } func (e *WintunEndpoint) dispatchLoop() { for { var buffer bufferv2.Buffer err := e.tun.ReadFunc(func(b []byte) { buffer = bufferv2.MakeWithData(b) }) if err != nil { break } ihl, ok := buffer.PullUp(0, 1) if !ok { buffer.Release() continue } var networkProtocol tcpip.NetworkProtocolNumber switch header.IPVersion(ihl.AsSlice()) { case header.IPv4Version: networkProtocol = header.IPv4ProtocolNumber case header.IPv6Version: networkProtocol = header.IPv6ProtocolNumber default: e.tun.Write(buffer.Flatten()) buffer.Release() continue } pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ Payload: buffer, IsForwardedPacket: true, }) dispatcher := e.dispatcher if dispatcher == nil { pkt.DecRef() return } dispatcher.DeliverNetworkPacket(networkProtocol, pkt) pkt.DecRef() } } func (e *WintunEndpoint) IsAttached() bool { return e.dispatcher != nil } func (e *WintunEndpoint) Wait() { } func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone } func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) { } func (e *WintunEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) { var n int for _, packet := range packetBufferList.AsSlice() { _, err := e.tun.write(packet.AsSlices()) if err != nil { return n, &tcpip.ErrAborted{} } n++ } return n, nil }