github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/tun/gvisor/channel.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package channel provides the implemention of channel-based data-link layer 16 // endpoints. Such endpoints allow injection of inbound packets and store 17 // outbound packets in a channel. 18 19 package tun 20 21 import ( 22 "sync" 23 24 "github.com/Asutorufa/yuhaiin/pkg/log" 25 "github.com/Asutorufa/yuhaiin/pkg/net/netlink" 26 "gvisor.dev/gvisor/pkg/buffer" 27 "gvisor.dev/gvisor/pkg/tcpip" 28 "gvisor.dev/gvisor/pkg/tcpip/header" 29 "gvisor.dev/gvisor/pkg/tcpip/stack" 30 ) 31 32 var _ stack.LinkEndpoint = (*Endpoint)(nil) 33 34 // Endpoint is link layer endpoint that stores outbound packets in a channel 35 // and allows injection of inbound packets. 36 type Endpoint struct { 37 wg sync.WaitGroup 38 mtu uint32 39 40 dev netlink.Tun 41 42 attached bool 43 } 44 45 // New creates a new channel endpoint. 46 func NewEndpoint(w netlink.Tun, mtu uint32) *Endpoint { 47 return &Endpoint{ 48 mtu: mtu, 49 dev: w, 50 } 51 } 52 53 // Close closes e. Further packet injections will return an error, and all pending 54 // packets are discarded. Close may be called concurrently with WritePackets. 55 func (e *Endpoint) Close() error { 56 e.dev.Close() 57 e.wg.Wait() 58 return nil 59 } 60 61 func (e *Endpoint) Writer() netlink.Tun { 62 return e.dev 63 } 64 65 // Attach saves the stack network-layer dispatcher for use later when packets 66 // are injected. 67 func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { 68 if dispatcher == nil && e.IsAttached() { 69 e.Close() 70 e.attached = false 71 } 72 73 if dispatcher != nil && !e.IsAttached() { 74 e.attached = true 75 e.wg.Add(1) 76 go func() { 77 defer e.wg.Done() 78 e.attachForward(dispatcher) 79 }() 80 } 81 } 82 83 func (e *Endpoint) attachForward(dispatcher stack.NetworkDispatcher) { 84 bufs := make([][]byte, e.dev.Tun().BatchSize()) 85 size := make([]int, e.dev.Tun().BatchSize()) 86 87 for i := range bufs { 88 bufs[i] = make([]byte, e.mtu) 89 } 90 91 for { 92 n, err := e.dev.Read(bufs, size) 93 for i := range n { 94 buf := bufs[i][:size[i]] 95 96 var p tcpip.NetworkProtocolNumber 97 switch header.IPVersion(buf) { 98 case header.IPv4Version: 99 p = header.IPv4ProtocolNumber 100 case header.IPv6Version: 101 p = header.IPv6ProtocolNumber 102 default: 103 continue 104 } 105 106 pkt := stack.NewPacketBuffer( 107 stack.PacketBufferOptions{ 108 Payload: buffer.MakeWithData(buf), 109 }) 110 dispatcher.DeliverNetworkPacket(p, pkt) 111 pkt.DecRef() 112 } 113 if err != nil { 114 log.Error("dev read failed", "err", err) 115 return 116 } 117 } 118 } 119 120 // IsAttached implements stack.LinkEndpoint.IsAttached. 121 func (e *Endpoint) IsAttached() bool { return e.attached } 122 123 // MTU implements stack.LinkEndpoint.MTU. It returns the value initialized 124 // during construction. 125 func (e *Endpoint) MTU() uint32 { return e.mtu } 126 127 // Capabilities implements stack.LinkEndpoint.Capabilities. 128 func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities { 129 return stack.CapabilityRXChecksumOffload 130 } 131 132 // MaxHeaderLength returns the maximum size of the link layer header. Given it 133 // doesn't have a header, it just returns 0. 134 func (*Endpoint) MaxHeaderLength() uint16 { return 0 } 135 136 // LinkAddress returns the link address of this endpoint. 137 func (e *Endpoint) LinkAddress() tcpip.LinkAddress { return "" } 138 139 // WritePackets stores outbound packets into the channel. 140 // Multiple concurrent calls are permitted. 141 func (e *Endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) { 142 bufs := [][]byte{} 143 for _, pkt := range pkts.AsSlice() { 144 view := pkt.ToView() 145 defer view.Release() 146 bufs = append(bufs, view.AsSlice()) 147 } 148 149 n, er := e.dev.Write(bufs) 150 if er != nil { 151 log.Error("write packet failed", "err", er) 152 if n == 0 { 153 return 0, &tcpip.ErrClosedForSend{} 154 } 155 } 156 157 return n, nil 158 } 159 160 // Wait implements stack.LinkEndpoint.Wait. 161 func (e *Endpoint) Wait() { e.wg.Wait() } 162 163 // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType. 164 func (*Endpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone } 165 166 // AddHeader implements stack.LinkEndpoint.AddHeader. 167 func (*Endpoint) AddHeader(*stack.PacketBuffer) {} 168 169 // ParseHeader implements stack.LinkEndpoint.ParseHeader. 170 func (*Endpoint) ParseHeader(*stack.PacketBuffer) bool { return true }