github.com/sagernet/sing-tun@v0.3.0-beta.5/stack_gvisor_filter.go (about)

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