client.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package dns
  2. import (
  3. "github.com/v2fly/v2ray-core/v5/common/errors"
  4. "github.com/v2fly/v2ray-core/v5/common/net"
  5. "github.com/v2fly/v2ray-core/v5/common/serial"
  6. "github.com/v2fly/v2ray-core/v5/features"
  7. )
  8. // IPOption is an object for IP query options.
  9. type IPOption struct {
  10. IPv4Enable bool
  11. IPv6Enable bool
  12. FakeEnable bool
  13. }
  14. func (opt IPOption) With(other IPOption) IPOption {
  15. return IPOption{
  16. IPv4Enable: opt.IPv4Enable && other.IPv4Enable,
  17. IPv6Enable: opt.IPv6Enable && other.IPv6Enable,
  18. FakeEnable: opt.FakeEnable && other.FakeEnable,
  19. }
  20. }
  21. func (opt IPOption) IsValid() bool {
  22. return opt.IPv4Enable || opt.IPv6Enable
  23. }
  24. // Client is a V2Ray feature for querying DNS information.
  25. //
  26. // v2ray:api:stable
  27. type Client interface {
  28. features.Feature
  29. // LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
  30. LookupIP(domain string) ([]net.IP, error)
  31. }
  32. // IPv4Lookup is an optional feature for querying IPv4 addresses only.
  33. //
  34. // v2ray:api:beta
  35. type IPv4Lookup interface {
  36. LookupIPv4(domain string) ([]net.IP, error)
  37. }
  38. // IPv6Lookup is an optional feature for querying IPv6 addresses only.
  39. //
  40. // v2ray:api:beta
  41. type IPv6Lookup interface {
  42. LookupIPv6(domain string) ([]net.IP, error)
  43. }
  44. // LookupIPWithOption is a helper function for querying DNS information from a dns.Client with dns.IPOption.
  45. //
  46. // v2ray:api:beta
  47. func LookupIPWithOption(client Client, domain string, option IPOption) ([]net.IP, error) {
  48. if option.FakeEnable {
  49. if clientWithFakeDNS, ok := client.(ClientWithFakeDNS); ok {
  50. client = clientWithFakeDNS.AsFakeDNSClient()
  51. }
  52. }
  53. if option.IPv4Enable && !option.IPv6Enable {
  54. if ipv4Lookup, ok := client.(IPv4Lookup); ok {
  55. return ipv4Lookup.LookupIPv4(domain)
  56. } else {
  57. return nil, errors.New("dns.Client doesn't implement IPv4Lookup")
  58. }
  59. }
  60. if option.IPv6Enable && !option.IPv4Enable {
  61. if ipv6Lookup, ok := client.(IPv6Lookup); ok {
  62. return ipv6Lookup.LookupIPv6(domain)
  63. } else {
  64. return nil, errors.New("dns.Client doesn't implement IPv6Lookup")
  65. }
  66. }
  67. return client.LookupIP(domain)
  68. }
  69. // ClientType returns the type of Client interface. Can be used for implementing common.HasType.
  70. //
  71. // v2ray:api:beta
  72. func ClientType() interface{} {
  73. return (*Client)(nil)
  74. }
  75. // ErrEmptyResponse indicates that DNS query succeeded but no answer was returned.
  76. var ErrEmptyResponse = errors.New("empty response")
  77. type RCodeError uint16
  78. func (e RCodeError) Error() string {
  79. return serial.Concat("rcode: ", uint16(e))
  80. }
  81. func RCodeFromError(err error) uint16 {
  82. if err == nil {
  83. return 0
  84. }
  85. cause := errors.Cause(err)
  86. if r, ok := cause.(RCodeError); ok {
  87. return uint16(r)
  88. }
  89. return 0
  90. }