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 }