diff --git a/dns/transport/local/local.go b/dns/transport/local/local.go index e5e8aef9..7f02c608 100644 --- a/dns/transport/local/local.go +++ b/dns/transport/local/local.go @@ -27,6 +27,7 @@ var _ adapter.DNSTransport = (*Transport)(nil) type Transport struct { dns.TransportAdapter + ctx context.Context hosts *hosts.File dialer N.Dialer } diff --git a/dns/transport/local/resolv_darwin_cgo.go b/dns/transport/local/resolv_darwin_cgo.go new file mode 100644 index 00000000..dfcb8a8a --- /dev/null +++ b/dns/transport/local/resolv_darwin_cgo.go @@ -0,0 +1,53 @@ +//go:build darwin && cgo + +package local + +/* +#include +#include +#include +#include +*/ +import "C" + +import ( + "time" + + E "github.com/sagernet/sing/common/exceptions" + + "github.com/miekg/dns" +) + +func dnsReadConfig(_ string) *dnsConfig { + if C.res_init() != 0 { + return &dnsConfig{ + servers: defaultNS, + search: dnsDefaultSearch(), + ndots: 1, + timeout: 5 * time.Second, + attempts: 2, + err: E.New("libresolv initialization failed"), + } + } + conf := &dnsConfig{ + ndots: 1, + timeout: 5 * time.Second, + attempts: int(C._res.retry), + } + for i := 0; i < int(C._res.nscount); i++ { + ns := C._res.nsaddr_list[i] + addr := C.inet_ntoa(ns.sin_addr) + if addr == nil { + continue + } + conf.servers = append(conf.servers, C.GoString(addr)) + } + for i := 0; ; i++ { + search := C._res.dnsrch[i] + if search == nil { + break + } + conf.search = append(conf.search, dns.Fqdn(C.GoString(search))) + } + return conf +} diff --git a/dns/transport/local/resolv_default.go b/dns/transport/local/resolv_default.go new file mode 100644 index 00000000..0a7d8810 --- /dev/null +++ b/dns/transport/local/resolv_default.go @@ -0,0 +1,23 @@ +package local + +import ( + "os" + "strings" + _ "unsafe" + + "github.com/miekg/dns" +) + +//go:linkname defaultNS net.defaultNS +var defaultNS []string + +func dnsDefaultSearch() []string { + hn, err := os.Hostname() + if err != nil { + return nil + } + if i := strings.IndexRune(hn, '.'); i >= 0 && i < len(hn)-1 { + return []string{dns.Fqdn(hn[i+1:])} + } + return nil +} diff --git a/dns/transport/local/resolv_unix.go b/dns/transport/local/resolv_unix.go index 6594ae41..c3953145 100644 --- a/dns/transport/local/resolv_unix.go +++ b/dns/transport/local/resolv_unix.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build !windows && !(darwin && cgo) package local @@ -9,7 +9,8 @@ import ( "os" "strings" "time" - _ "unsafe" + + "github.com/miekg/dns" ) func dnsReadConfig(name string) *dnsConfig { @@ -69,13 +70,13 @@ func dnsReadConfig(name string) *dnsConfig { } case "domain": if len(f) > 1 { - conf.search = []string{ensureRooted(f[1])} + conf.search = []string{dns.Fqdn(f[1])} } case "search": conf.search = make([]string, 0, len(f)-1) for i := 1; i < len(f); i++ { - name := ensureRooted(f[i]) + name := dns.Fqdn(f[i]) if name == "." { continue } @@ -137,27 +138,6 @@ func dnsReadConfig(name string) *dnsConfig { return conf } -//go:linkname defaultNS net.defaultNS -var defaultNS []string - -func dnsDefaultSearch() []string { - hn, err := os.Hostname() - if err != nil { - return nil - } - if i := strings.IndexRune(hn, '.'); i >= 0 && i < len(hn)-1 { - return []string{ensureRooted(hn[i+1:])} - } - return nil -} - -func ensureRooted(s string) string { - if len(s) > 0 && s[len(s)-1] == '.' { - return s - } - return s + "." -} - const big = 0xFFFFFF func dtoi(s string) (n int, i int, ok bool) { diff --git a/dns/transport_manager.go b/dns/transport_manager.go index 4497923b..8666a1b9 100644 --- a/dns/transport_manager.go +++ b/dns/transport_manager.go @@ -56,12 +56,12 @@ func (m *TransportManager) Start(stage adapter.StartStage) error { } m.started = true m.stage = stage - outbounds := m.transports + transports := m.transports m.access.Unlock() if stage == adapter.StartStateStart { return m.startTransports(m.transports) } else { - for _, outbound := range outbounds { + for _, outbound := range transports { err := adapter.LegacyStart(outbound, stage) if err != nil { return E.Cause(err, stage, " dns/", outbound.Type(), "[", outbound.Tag(), "]") diff --git a/protocol/tun/hook.go b/protocol/tun/hook.go new file mode 100644 index 00000000..1afa643f --- /dev/null +++ b/protocol/tun/hook.go @@ -0,0 +1,3 @@ +package tun + +var HookBeforeCreatePlatformInterface func() diff --git a/protocol/tun/inbound.go b/protocol/tun/inbound.go index 00cc0561..088780ed 100644 --- a/protocol/tun/inbound.go +++ b/protocol/tun/inbound.go @@ -361,6 +361,9 @@ func (t *Inbound) Start(stage adapter.StartStage) error { if t.platformInterface != nil { tunInterface, err = t.platformInterface.OpenTun(&tunOptions, t.platformOptions) } else { + if HookBeforeCreatePlatformInterface != nil { + HookBeforeCreatePlatformInterface() + } tunInterface, err = tun.New(tunOptions) } monitor.Finish()