package hosts import ( "context" "net/netip" "os" "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/dns" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/service/filemanager" mDNS "github.com/miekg/dns" ) func RegisterTransport(registry *dns.TransportRegistry) { dns.RegisterTransport[option.HostsDNSServerOptions](registry, C.DNSTypeHosts, NewTransport) } var _ adapter.DNSTransport = (*Transport)(nil) type Transport struct { dns.TransportAdapter files []*File predefined map[string][]netip.Addr } func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.HostsDNSServerOptions) (adapter.DNSTransport, error) { var ( files []*File predefined = make(map[string][]netip.Addr) ) if len(options.Path) == 0 { files = append(files, NewFile(DefaultPath)) } else { for _, path := range options.Path { files = append(files, NewFile(filemanager.BasePath(ctx, os.ExpandEnv(path)))) } } if options.Predefined != nil { for _, entry := range options.Predefined.Entries() { predefined[mDNS.CanonicalName(entry.Key)] = entry.Value } } return &Transport{ TransportAdapter: dns.NewTransportAdapter(C.DNSTypeHosts, tag, nil), files: files, predefined: predefined, }, nil } func (t *Transport) Start(stage adapter.StartStage) error { return nil } func (t *Transport) Close() error { return nil } func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) { question := message.Question[0] domain := mDNS.CanonicalName(question.Name) if question.Qtype == mDNS.TypeA || question.Qtype == mDNS.TypeAAAA { if addresses, ok := t.predefined[domain]; ok { return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil } for _, file := range t.files { addresses := file.Lookup(domain) if len(addresses) > 0 { return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil } } } return &mDNS.Msg{ MsgHdr: mDNS.MsgHdr{ Id: message.Id, Rcode: mDNS.RcodeNameError, Response: true, }, Question: []mDNS.Question{question}, }, nil }