Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/.idea/
/vendor/
.DS_Store
.worktrees/
!/README.md
/*.md
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ build:
GOOS=linux GOARCH=386 go build -v -tags with_gvisor .
GOOS=linux GOARCH=arm go build -v -tags with_gvisor .
GOOS=android GOARCH=arm64 go build -v -tags with_gvisor .
GOOS=freebsd GOARCH=amd64 go build -v -tags with_gvisor .
GOOS=windows GOARCH=amd64 go build -v -tags with_gvisor .
GOOS=freebsd GOARCH=amd64 go build -v -tags with_gvisor .

fmt:
@gofumpt -l -w .
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"encoding/binary"
"fmt"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
)

// PseudoHeaderChecksum calculates the pseudo-header checksum for the given
Expand Down
2 changes: 1 addition & 1 deletion internal/gtcpip/header/eth.go → gtcpip/header/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package header
import (
"encoding/binary"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/gtcpip"
)

const (
Expand Down
4 changes: 2 additions & 2 deletions internal/gtcpip/header/icmpv4.go → gtcpip/header/icmpv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package header
import (
"encoding/binary"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
)

// ICMPv4 represents an ICMPv4 header stored in a byte array.
Expand Down
4 changes: 2 additions & 2 deletions internal/gtcpip/header/icmpv6.go → gtcpip/header/icmpv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package header
import (
"encoding/binary"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
)

// ICMPv6 represents an ICMPv6 header stored in a byte array.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package header
import (
"net/netip"

tcpip "github.com/sagernet/sing-tun/internal/gtcpip"
tcpip "github.com/sagernet/sing-tun/gtcpip"
)

const (
Expand Down
4 changes: 2 additions & 2 deletions internal/gtcpip/header/ipv4.go → gtcpip/header/ipv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import (
"net/netip"
"time"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
"github.com/sagernet/sing/common"
)

Expand Down
2 changes: 1 addition & 1 deletion internal/gtcpip/header/ipv6.go → gtcpip/header/ipv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"fmt"
"net/netip"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/gtcpip"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"fmt"
"math"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing/common"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ package header
import (
"encoding/binary"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/gtcpip"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package header

import "github.com/sagernet/sing-tun/internal/gtcpip"
import "github.com/sagernet/sing-tun/gtcpip"

// NDPNeighborAdvert is an NDP Neighbor Advertisement message. It will
// only contain the body of an ICMPv6 packet.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

package header

import "github.com/sagernet/sing-tun/internal/gtcpip"
import "github.com/sagernet/sing-tun/gtcpip"

// NDPNeighborSolicit is an NDP Neighbor Solicitation message. It will only
// contain the body of an ICMPv6 packet.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"math"
"time"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing/common"
)

Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions internal/gtcpip/header/tcp.go → gtcpip/header/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ package header
import (
"encoding/binary"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/internal/gtcpip/seqnum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip/seqnum"

"github.com/google/btree"
)
Expand Down
4 changes: 2 additions & 2 deletions internal/gtcpip/header/udp.go → gtcpip/header/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
"encoding/binary"
"math"

"github.com/sagernet/sing-tun/internal/gtcpip"
"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip"
"github.com/sagernet/sing-tun/gtcpip/checksum"
)

const (
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion internal/checksum_test/sum_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"crypto/rand"
"testing"

"github.com/sagernet/sing-tun/internal/gtcpip/checksum"
"github.com/sagernet/sing-tun/gtcpip/checksum"
"github.com/sagernet/sing-tun/internal/tschecksum"
)

Expand Down
174 changes: 174 additions & 0 deletions monitor_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package tun

import (
"net"
"net/netip"
"os"
"sync"

"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
"github.com/sagernet/sing/common/x/list"
"golang.org/x/net/route"
"golang.org/x/sys/unix"
)

var _ NetworkUpdateMonitor = (*networkUpdateMonitor)(nil)

type networkUpdateMonitor struct {
access sync.Mutex
callbacks list.List[NetworkUpdateCallback]
routeSocketFile *os.File
closeOnce sync.Once
done chan struct{}
logger logger.Logger
}

func NewNetworkUpdateMonitor(logger logger.Logger) (NetworkUpdateMonitor, error) {

return &networkUpdateMonitor{
logger: logger,
done: make(chan struct{}),
}, nil
}

// Close implements NetworkUpdateMonitor.
func (m *networkUpdateMonitor) Close() error {
m.closeOnce.Do(func() {
close(m.done)
})
return nil
}

// Start implements NetworkUpdateMonitor.
func (m *networkUpdateMonitor) Start() error {
go m.loopUpdate()
return nil
}

func (m *networkUpdateMonitor) loopUpdate() {
for {
select {
case <-m.done:
return
default:
}
err := m.loopUpdate0()
if err != nil {
m.logger.Error("listen network update: ", err)
return
}
}
}

func (m *networkUpdateMonitor) loopUpdate0() error {
routeSocket, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, 0)
if err != nil {
return err
}
err = unix.SetNonblock(routeSocket, true)
if err != nil {
unix.Close(routeSocket)
return err
}
routeSocketFile := os.NewFile(uintptr(routeSocket), "route")
defer routeSocketFile.Close()
m.routeSocketFile = routeSocketFile
m.loopUpdate1(routeSocketFile)
return nil
}

func (m *networkUpdateMonitor) loopUpdate1(routeSocketFile *os.File) {
buffer := buf.NewPacket()
defer buffer.Release()

done := make(chan struct{})
go func() {
select {
case <-m.done:
routeSocketFile.Close()
case <-done:
}
}()
n, err := routeSocketFile.Read(buffer.FreeBytes())
close(done)
if err != nil {
return
}
buffer.Truncate(n)

messages, err := route.ParseRIB(route.RIBTypeRoute, buffer.Bytes())
if err != nil {
return
}

for _, message := range messages {
if _, isRouteMessage := message.(*route.RouteMessage); isRouteMessage {
m.emit()
return
}
}
}

// checkUpdate finds the first IPv4 default gateway and emits an update event.
func (m *defaultInterfaceMonitor) checkUpdate() error {
var defaultInterface *control.Interface
ribMessage, err := route.FetchRIB(unix.AF_INET, route.RIBTypeRoute, 0)
if err != nil {
return err
}
routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage)
if err != nil {
return err
}

for _, rawRouteMessage := range routeMessages {
routeMessage := rawRouteMessage.(*route.RouteMessage)
if len(routeMessage.Addrs) <= unix.RTAX_NETMASK {
continue
}
destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr)
if !isIPv4Destination || destination.IP != netip.IPv4Unspecified().As4() {
continue
}
mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr)
if !isIPv4Mask {
continue
}
if ones, _ := net.IPMask(mask.IP[:]).Size(); ones != 0 {
continue
}
flag := unix.RTF_UP | unix.RTF_GATEWAY | unix.RTF_STATIC
if routeMessage.Flags&(flag) != flag {
continue
}
routeInterface, err := m.interfaceFinder.ByIndex(routeMessage.Index)
if err != nil {
return err
}
if routeInterface.Flags&net.FlagLoopback != 0 {
continue
}
defaultInterface = routeInterface
break
}

if defaultInterface == nil {
if m.underNetworkExtension {
m.logger.Warn("Not implemented: UnderNetworkExtension")
}
return ErrNoRoute
}
newInterface, err := m.interfaceFinder.ByIndex(defaultInterface.Index)
if err != nil {
return E.Cause(err, "find updated interface: ", defaultInterface.Name)
}
oldInterface := m.defaultInterface.Swap(newInterface)
if oldInterface != nil && oldInterface.Equals(*newInterface) {
return nil
}
m.emit(newInterface, 0)
return nil
}
2 changes: 1 addition & 1 deletion monitor_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !(linux || windows || darwin)
//go:build !(linux || windows || darwin || freebsd)

package tun

Expand Down
2 changes: 1 addition & 1 deletion monitor_shared.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build linux || windows || darwin
//go:build linux || windows || darwin || freebsd

package tun

Expand Down
2 changes: 1 addition & 1 deletion nfqueue_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"errors"
"sync/atomic"

"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing-tun/gtcpip/header"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
Expand Down
2 changes: 1 addition & 1 deletion ping/destination.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"time"

"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing-tun/gtcpip/header"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
Expand Down
2 changes: 1 addition & 1 deletion ping/destination_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"net/netip"

"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing-tun/gtcpip/header"
"github.com/sagernet/sing/common/buf"
)

Expand Down
2 changes: 1 addition & 1 deletion ping/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"sync/atomic"
"time"

"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing-tun/gtcpip/header"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/control"
Expand Down
2 changes: 1 addition & 1 deletion ping/ping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

"github.com/sagernet/gvisor/pkg/rand"
"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing-tun/gtcpip/header"
"github.com/sagernet/sing-tun/ping"
"github.com/sagernet/sing/common/buf"

Expand Down
Loading