sing-box/transport/openconnect/device_system_stack.go

117 lines
2.9 KiB
Go

//go:build with_gvisor
package openconnect
import (
"net/netip"
"github.com/sagernet/sing-tun/gtcpip/header"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
)
var _ Device = (*systemStackDevice)(nil)
type systemStackDevice struct {
*systemDevice
stackDevice *stackDevice
}
func newSystemStackDevice(options DeviceOptions) (*systemStackDevice, error) {
system, err := newSystemDevice(options)
if err != nil {
return nil, err
}
stackOptions := options
stackOptions.System = false
stackOptions.Name = system.options.Name
stackOptions.ExcludeInterface = []string{system.options.Name}
stackDevice, err := newStackDevice(stackOptions)
if err != nil {
system.Close()
return nil, err
}
return &systemStackDevice{
systemDevice: system,
stackDevice: stackDevice,
}, nil
}
func (d *systemStackDevice) SetPacketWriter(writer PacketWriter) {
d.systemDevice.SetPacketWriter(writer)
d.stackDevice.SetPacketWriter(writer)
}
func (d *systemStackDevice) Start() error {
err := d.stackDevice.Start()
if err != nil {
return err
}
err = d.systemDevice.Start()
return err
}
func (d *systemStackDevice) UpdateConfiguration(configuration Configuration) error {
err := d.systemDevice.UpdateConfiguration(configuration)
if err != nil {
return err
}
return d.stackDevice.UpdateConfiguration(configuration)
}
func (d *systemStackDevice) WriteInboundBuffers(packetBuffers []*buf.Buffer) error {
return d.systemDevice.processInboundBuffers(packetBuffers, d.writeBuffers)
}
func (d *systemStackDevice) writeBuffers(packetBuffers []*buf.Buffer) error {
addresses := d.systemDevice.configurationAddresses()
runStart := 0
runUsesSystemDevice := false
var writeErr error
for i, packetBuffer := range packetBuffers {
destination := packetDestination(packetBuffer.Bytes())
useSystemDevice := false
for _, prefix := range addresses {
if prefix.Contains(destination) {
useSystemDevice = true
break
}
}
if i > runStart && useSystemDevice != runUsesSystemDevice {
var err error
if runUsesSystemDevice {
err = d.systemDevice.writeBuffers(packetBuffers[runStart:i])
} else {
err = d.stackDevice.writeBuffers(packetBuffers[runStart:i])
}
writeErr = E.Errors(writeErr, err)
runStart = i
}
if i == runStart {
runUsesSystemDevice = useSystemDevice
}
}
if runStart == len(packetBuffers) {
return writeErr
}
if runUsesSystemDevice {
return E.Errors(writeErr, d.systemDevice.writeBuffers(packetBuffers[runStart:]))
}
return E.Errors(writeErr, d.stackDevice.writeBuffers(packetBuffers[runStart:]))
}
func packetDestination(packet []byte) netip.Addr {
switch header.IPVersion(packet) {
case header.IPv4Version:
return header.IPv4(packet).DestinationAddr()
case header.IPv6Version:
return header.IPv6(packet).DestinationAddr()
default:
return netip.Addr{}
}
}
func (d *systemStackDevice) Close() error {
return E.Errors(d.stackDevice.Close(), d.systemDevice.Close())
}