mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
119 lines
2.5 KiB
Go
119 lines
2.5 KiB
Go
package tun
|
|
|
|
import (
|
|
"os"
|
|
|
|
"github.com/sagernet/sing/common"
|
|
"github.com/sagernet/sing/common/buf"
|
|
"github.com/sagernet/sing/common/rw"
|
|
|
|
gBuffer "gvisor.dev/gvisor/pkg/buffer"
|
|
"gvisor.dev/gvisor/pkg/tcpip"
|
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
|
)
|
|
|
|
var _ stack.LinkEndpoint = (*PosixEndpoint)(nil)
|
|
|
|
type PosixEndpoint struct {
|
|
fd uintptr
|
|
mtu uint32
|
|
file *os.File
|
|
dispatcher stack.NetworkDispatcher
|
|
}
|
|
|
|
func NewPosixEndpoint(tunFd uintptr, tunMtu uint32) (stack.LinkEndpoint, error) {
|
|
return &PosixEndpoint{
|
|
fd: tunFd,
|
|
mtu: tunMtu,
|
|
file: os.NewFile(tunFd, "tun"),
|
|
}, nil
|
|
}
|
|
|
|
func (e *PosixEndpoint) MTU() uint32 {
|
|
return e.mtu
|
|
}
|
|
|
|
func (e *PosixEndpoint) MaxHeaderLength() uint16 {
|
|
return 0
|
|
}
|
|
|
|
func (e *PosixEndpoint) LinkAddress() tcpip.LinkAddress {
|
|
return ""
|
|
}
|
|
|
|
func (e *PosixEndpoint) Capabilities() stack.LinkEndpointCapabilities {
|
|
return stack.CapabilityNone
|
|
}
|
|
|
|
func (e *PosixEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
|
|
if dispatcher == nil && e.dispatcher != nil {
|
|
e.dispatcher = nil
|
|
return
|
|
}
|
|
if dispatcher != nil && e.dispatcher == nil {
|
|
e.dispatcher = dispatcher
|
|
go e.dispatchLoop()
|
|
}
|
|
}
|
|
|
|
func (e *PosixEndpoint) dispatchLoop() {
|
|
_buffer := buf.StackNewPacket()
|
|
defer common.KeepAlive(_buffer)
|
|
buffer := common.Dup(_buffer)
|
|
defer buffer.Release()
|
|
for {
|
|
n, err := e.file.Read(buffer.FreeBytes())
|
|
if err != nil {
|
|
break
|
|
}
|
|
var view gBuffer.View
|
|
view.Append(buffer.To(n))
|
|
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
|
|
Payload: view,
|
|
IsForwardedPacket: true,
|
|
})
|
|
defer pkt.DecRef()
|
|
var p tcpip.NetworkProtocolNumber
|
|
ipHeader, ok := pkt.Data().PullUp(1)
|
|
if !ok {
|
|
continue
|
|
}
|
|
switch header.IPVersion(ipHeader) {
|
|
case header.IPv4Version:
|
|
p = header.IPv4ProtocolNumber
|
|
case header.IPv6Version:
|
|
p = header.IPv6ProtocolNumber
|
|
default:
|
|
continue
|
|
}
|
|
e.dispatcher.DeliverNetworkPacket(p, pkt)
|
|
}
|
|
}
|
|
|
|
func (e *PosixEndpoint) IsAttached() bool {
|
|
return e.dispatcher != nil
|
|
}
|
|
|
|
func (e *PosixEndpoint) Wait() {
|
|
}
|
|
|
|
func (e *PosixEndpoint) ARPHardwareType() header.ARPHardwareType {
|
|
return header.ARPHardwareNone
|
|
}
|
|
|
|
func (e *PosixEndpoint) AddHeader(buffer *stack.PacketBuffer) {
|
|
}
|
|
|
|
func (e *PosixEndpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) {
|
|
var n int
|
|
for _, packet := range pkts.AsSlice() {
|
|
_, err := rw.WriteV(e.fd, packet.Slices())
|
|
if err != nil {
|
|
return n, &tcpip.ErrAborted{}
|
|
}
|
|
n++
|
|
}
|
|
return n, nil
|
|
}
|