predefined.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package transport
  2. import (
  3. "context"
  4. "github.com/sagernet/sing-box/adapter"
  5. C "github.com/sagernet/sing-box/constant"
  6. "github.com/sagernet/sing-box/dns"
  7. "github.com/sagernet/sing-box/log"
  8. "github.com/sagernet/sing-box/option"
  9. "github.com/sagernet/sing/common"
  10. E "github.com/sagernet/sing/common/exceptions"
  11. mDNS "github.com/miekg/dns"
  12. )
  13. var _ adapter.DNSTransport = (*PredefinedTransport)(nil)
  14. func RegisterPredefined(registry *dns.TransportRegistry) {
  15. dns.RegisterTransport[option.PredefinedDNSServerOptions](registry, C.DNSTypePreDefined, NewPredefined)
  16. }
  17. type PredefinedTransport struct {
  18. dns.TransportAdapter
  19. responses []*predefinedResponse
  20. }
  21. type predefinedResponse struct {
  22. questions []mDNS.Question
  23. answer *mDNS.Msg
  24. }
  25. func NewPredefined(ctx context.Context, logger log.ContextLogger, tag string, options option.PredefinedDNSServerOptions) (adapter.DNSTransport, error) {
  26. var responses []*predefinedResponse
  27. for _, response := range options.Responses {
  28. questions, msg, err := response.Build()
  29. if err != nil {
  30. return nil, err
  31. }
  32. responses = append(responses, &predefinedResponse{
  33. questions: questions,
  34. answer: msg,
  35. })
  36. }
  37. if len(responses) == 0 {
  38. return nil, E.New("empty predefined responses")
  39. }
  40. return &PredefinedTransport{
  41. TransportAdapter: dns.NewTransportAdapter(C.DNSTypePreDefined, tag, nil),
  42. responses: responses,
  43. }, nil
  44. }
  45. func (t *PredefinedTransport) Reset() {
  46. }
  47. func (t *PredefinedTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  48. for _, response := range t.responses {
  49. for _, question := range response.questions {
  50. if func() bool {
  51. if question.Name == "" && question.Qtype == mDNS.TypeNone {
  52. return true
  53. } else if question.Name == "" {
  54. return common.Any(message.Question, func(it mDNS.Question) bool {
  55. return it.Qtype == question.Qtype
  56. })
  57. } else if question.Qtype == mDNS.TypeNone {
  58. return common.Any(message.Question, func(it mDNS.Question) bool {
  59. return it.Name == question.Name
  60. })
  61. } else {
  62. return common.Contains(message.Question, question)
  63. }
  64. }() {
  65. copyAnswer := *response.answer
  66. copyAnswer.Id = message.Id
  67. copyAnswer.Question = message.Question
  68. return &copyAnswer, nil
  69. }
  70. }
  71. }
  72. return nil, dns.RcodeNameError
  73. }