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

     1  //go:build with_gvisor && darwin
     2  
     3  package tun
     4  
     5  import (
     6  	"github.com/sagernet/sing/common/bufio"
     7  
     8  	"github.com/MerlinKodo/gvisor/pkg/buffer"
     9  	"github.com/MerlinKodo/gvisor/pkg/tcpip"
    10  	"github.com/MerlinKodo/gvisor/pkg/tcpip/header"
    11  	"github.com/MerlinKodo/gvisor/pkg/tcpip/stack"
    12  )
    13  
    14  var _ GVisorTun = (*NativeTun)(nil)
    15  
    16  func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
    17  	return &DarwinEndpoint{tun: t}, nil
    18  }
    19  
    20  var _ stack.LinkEndpoint = (*DarwinEndpoint)(nil)
    21  
    22  type DarwinEndpoint struct {
    23  	tun        *NativeTun
    24  	dispatcher stack.NetworkDispatcher
    25  }
    26  
    27  func (e *DarwinEndpoint) MTU() uint32 {
    28  	return e.tun.mtu
    29  }
    30  
    31  func (e *DarwinEndpoint) MaxHeaderLength() uint16 {
    32  	return 0
    33  }
    34  
    35  func (e *DarwinEndpoint) LinkAddress() tcpip.LinkAddress {
    36  	return ""
    37  }
    38  
    39  func (e *DarwinEndpoint) Capabilities() stack.LinkEndpointCapabilities {
    40  	return stack.CapabilityNone
    41  }
    42  
    43  func (e *DarwinEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
    44  	if dispatcher == nil && e.dispatcher != nil {
    45  		e.dispatcher = nil
    46  		return
    47  	}
    48  	if dispatcher != nil && e.dispatcher == nil {
    49  		e.dispatcher = dispatcher
    50  		go e.dispatchLoop()
    51  	}
    52  }
    53  
    54  func (e *DarwinEndpoint) dispatchLoop() {
    55  	packetBuffer := make([]byte, e.tun.mtu+4)
    56  	for {
    57  		n, err := e.tun.tunFile.Read(packetBuffer)
    58  		if err != nil {
    59  			break
    60  		}
    61  		packet := packetBuffer[4:n]
    62  		var networkProtocol tcpip.NetworkProtocolNumber
    63  		switch header.IPVersion(packet) {
    64  		case header.IPv4Version:
    65  			networkProtocol = header.IPv4ProtocolNumber
    66  			if header.IPv4(packet).DestinationAddress().As4() == e.tun.inet4Address {
    67  				e.tun.tunFile.Write(packetBuffer[:n])
    68  				continue
    69  			}
    70  		case header.IPv6Version:
    71  			networkProtocol = header.IPv6ProtocolNumber
    72  			if header.IPv6(packet).DestinationAddress().As16() == e.tun.inet6Address {
    73  				e.tun.tunFile.Write(packetBuffer[:n])
    74  				continue
    75  			}
    76  		default:
    77  			e.tun.tunFile.Write(packetBuffer[:n])
    78  			continue
    79  		}
    80  		pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
    81  			Payload:           buffer.MakeWithData(packetBuffer[4:n]),
    82  			IsForwardedPacket: true,
    83  		})
    84  		pkt.NetworkProtocolNumber = networkProtocol
    85  		dispatcher := e.dispatcher
    86  		if dispatcher == nil {
    87  			pkt.DecRef()
    88  			return
    89  		}
    90  		dispatcher.DeliverNetworkPacket(networkProtocol, pkt)
    91  		pkt.DecRef()
    92  	}
    93  }
    94  
    95  func (e *DarwinEndpoint) IsAttached() bool {
    96  	return e.dispatcher != nil
    97  }
    98  
    99  func (e *DarwinEndpoint) Wait() {
   100  }
   101  
   102  func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType {
   103  	return header.ARPHardwareNone
   104  }
   105  
   106  func (e *DarwinEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
   107  }
   108  
   109  func (e *DarwinEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
   110  	return true
   111  }
   112  
   113  func (e *DarwinEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
   114  	var n int
   115  	for _, packet := range packetBufferList.AsSlice() {
   116  		var packetHeader []byte
   117  		switch packet.NetworkProtocolNumber {
   118  		case header.IPv4ProtocolNumber:
   119  			packetHeader = packetHeader4[:]
   120  		case header.IPv6ProtocolNumber:
   121  			packetHeader = packetHeader6[:]
   122  		}
   123  		_, err := bufio.WriteVectorised(e.tun.tunWriter, append([][]byte{packetHeader}, packet.AsSlices()...))
   124  		if err != nil {
   125  			return n, &tcpip.ErrAborted{}
   126  		}
   127  		n++
   128  	}
   129  	return n, nil
   130  }