resolv_darwin.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package local
  2. import (
  3. "context"
  4. "net/netip"
  5. "syscall"
  6. "time"
  7. "unsafe"
  8. E "github.com/sagernet/sing/common/exceptions"
  9. "github.com/miekg/dns"
  10. )
  11. func dnsReadConfig(_ context.Context, _ string) *dnsConfig {
  12. resStateSize := unsafe.Sizeof(_C_struct___res_state{})
  13. var state *_C_struct___res_state
  14. if resStateSize > 0 {
  15. mem := _C_malloc(resStateSize)
  16. defer _C_free(mem)
  17. memSlice := unsafe.Slice((*byte)(mem), resStateSize)
  18. clear(memSlice)
  19. state = (*_C_struct___res_state)(unsafe.Pointer(&memSlice[0]))
  20. }
  21. if err := ResNinit(state); err != nil {
  22. return &dnsConfig{
  23. servers: defaultNS,
  24. search: dnsDefaultSearch(),
  25. ndots: 1,
  26. timeout: 5 * time.Second,
  27. attempts: 2,
  28. err: E.Cause(err, "libresolv initialization failed"),
  29. }
  30. }
  31. defer ResNclose(state)
  32. conf := &dnsConfig{
  33. ndots: 1,
  34. timeout: 5 * time.Second,
  35. attempts: int(state.Retry),
  36. }
  37. for i := 0; i < int(state.Nscount); i++ {
  38. addr := parseRawSockaddr(&state.Nsaddrlist[i])
  39. if addr.IsValid() {
  40. conf.servers = append(conf.servers, addr.String())
  41. }
  42. }
  43. for i := 0; ; i++ {
  44. search := state.Dnsrch[i]
  45. if search == nil {
  46. break
  47. }
  48. name := dns.Fqdn(GoString(search))
  49. if name == "" {
  50. continue
  51. }
  52. conf.search = append(conf.search, name)
  53. }
  54. return conf
  55. }
  56. func parseRawSockaddr(rawSockaddr *syscall.RawSockaddr) netip.Addr {
  57. switch rawSockaddr.Family {
  58. case syscall.AF_INET:
  59. sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rawSockaddr))
  60. return netip.AddrFrom4(sa.Addr)
  61. case syscall.AF_INET6:
  62. sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rawSockaddr))
  63. return netip.AddrFrom16(sa.Addr)
  64. default:
  65. return netip.Addr{}
  66. }
  67. }