github.com/metacubex/sing-tun@v0.2.7-0.20240512075008-89e7c6208eec/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/metacubex/gvisor/pkg/buffer" 9 "github.com/metacubex/gvisor/pkg/tcpip" 10 "github.com/metacubex/gvisor/pkg/tcpip/header" 11 "github.com/metacubex/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.CapabilityRXChecksumOffload 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+PacketOffset) 56 for { 57 n, err := e.tun.tunFile.Read(packetBuffer) 58 if err != nil { 59 break 60 } 61 packet := packetBuffer[PacketOffset: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.PacketBuffer) { 107 } 108 109 func (e *DarwinEndpoint) ParseHeader(ptr *stack.PacketBuffer) 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 _, err := bufio.WriteVectorised(e.tun, packet.AsSlices()) 117 if err != nil { 118 return n, &tcpip.ErrAborted{} 119 } 120 n++ 121 } 122 return n, nil 123 }