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

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