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 }