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 }