github.com/MerlinKodo/sing-tun@v0.1.15/stack_gvisor_filter.go (about)

     1  //go:build with_gvisor
     2  
     3  package tun
     4  
     5  import (
     6  	"github.com/MerlinKodo/gvisor/pkg/tcpip"
     7  	"github.com/MerlinKodo/gvisor/pkg/tcpip/header"
     8  	"github.com/MerlinKodo/gvisor/pkg/tcpip/stack"
     9  	"github.com/sagernet/sing/common/bufio"
    10  	N "github.com/sagernet/sing/common/network"
    11  )
    12  
    13  var _ stack.LinkEndpoint = (*LinkEndpointFilter)(nil)
    14  
    15  type LinkEndpointFilter struct {
    16  	stack.LinkEndpoint
    17  	Writer N.VectorisedWriter
    18  }
    19  
    20  func (w *LinkEndpointFilter) Attach(dispatcher stack.NetworkDispatcher) {
    21  	w.LinkEndpoint.Attach(&networkDispatcherFilter{dispatcher, w.Writer})
    22  }
    23  
    24  var _ stack.NetworkDispatcher = (*networkDispatcherFilter)(nil)
    25  
    26  type networkDispatcherFilter struct {
    27  	stack.NetworkDispatcher
    28  	writer N.VectorisedWriter
    29  }
    30  
    31  func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
    32  	var network header.Network
    33  	if protocol == header.IPv4ProtocolNumber {
    34  		if headerPackets, loaded := pkt.Data().PullUp(header.IPv4MinimumSize); loaded {
    35  			network = header.IPv4(headerPackets)
    36  		}
    37  	} else {
    38  		if headerPackets, loaded := pkt.Data().PullUp(header.IPv6MinimumSize); loaded {
    39  			network = header.IPv6(headerPackets)
    40  		}
    41  	}
    42  	if network == nil {
    43  		w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
    44  		return
    45  	}
    46  	destination := AddrFromAddress(network.DestinationAddress())
    47  	if destination.IsGlobalUnicast() {
    48  		w.NetworkDispatcher.DeliverNetworkPacket(protocol, pkt)
    49  		return
    50  	}
    51  	_, _ = bufio.WriteVectorised(w.writer, pkt.AsSlices())
    52  }