dns_record.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package option
  2. import (
  3. "encoding/base64"
  4. "github.com/sagernet/sing/common/buf"
  5. E "github.com/sagernet/sing/common/exceptions"
  6. "github.com/sagernet/sing/common/json"
  7. M "github.com/sagernet/sing/common/metadata"
  8. "github.com/miekg/dns"
  9. )
  10. type DNSRCode int
  11. func (r DNSRCode) MarshalJSON() ([]byte, error) {
  12. rCodeValue, loaded := dns.RcodeToString[int(r)]
  13. if loaded {
  14. return json.Marshal(rCodeValue)
  15. }
  16. return json.Marshal(int(r))
  17. }
  18. func (r *DNSRCode) UnmarshalJSON(bytes []byte) error {
  19. var intValue int
  20. err := json.Unmarshal(bytes, &intValue)
  21. if err == nil {
  22. *r = DNSRCode(intValue)
  23. return nil
  24. }
  25. var stringValue string
  26. err = json.Unmarshal(bytes, &stringValue)
  27. if err != nil {
  28. return err
  29. }
  30. rCodeValue, loaded := dns.StringToRcode[stringValue]
  31. if !loaded {
  32. return E.New("unknown rcode: " + stringValue)
  33. }
  34. *r = DNSRCode(rCodeValue)
  35. return nil
  36. }
  37. func (r *DNSRCode) Build() int {
  38. if r == nil {
  39. return dns.RcodeSuccess
  40. }
  41. return int(*r)
  42. }
  43. type DNSRecordOptions struct {
  44. dns.RR
  45. fromBase64 bool
  46. }
  47. func (o DNSRecordOptions) MarshalJSON() ([]byte, error) {
  48. if o.fromBase64 {
  49. buffer := buf.Get(dns.Len(o.RR))
  50. defer buf.Put(buffer)
  51. offset, err := dns.PackRR(o.RR, buffer, 0, nil, false)
  52. if err != nil {
  53. return nil, err
  54. }
  55. return json.Marshal(base64.StdEncoding.EncodeToString(buffer[:offset]))
  56. }
  57. return json.Marshal(o.RR.String())
  58. }
  59. func (o *DNSRecordOptions) UnmarshalJSON(data []byte) error {
  60. var stringValue string
  61. err := json.Unmarshal(data, &stringValue)
  62. if err != nil {
  63. return err
  64. }
  65. binary, err := base64.StdEncoding.DecodeString(stringValue)
  66. if err == nil {
  67. return o.unmarshalBase64(binary)
  68. }
  69. record, err := dns.NewRR(stringValue)
  70. if err != nil {
  71. return err
  72. }
  73. if a, isA := record.(*dns.A); isA {
  74. a.A = M.AddrFromIP(a.A).Unmap().AsSlice()
  75. }
  76. o.RR = record
  77. return nil
  78. }
  79. func (o *DNSRecordOptions) unmarshalBase64(binary []byte) error {
  80. record, _, err := dns.UnpackRR(binary, 0)
  81. if err != nil {
  82. return E.New("parse binary DNS record")
  83. }
  84. o.RR = record
  85. o.fromBase64 = true
  86. return nil
  87. }
  88. func (o DNSRecordOptions) Build() dns.RR {
  89. return o.RR
  90. }