diff --git a/pkg/hosts/hosts.go b/pkg/hosts/hosts.go index 4eb5c98..40f8776 100644 --- a/pkg/hosts/hosts.go +++ b/pkg/hosts/hosts.go @@ -2,6 +2,7 @@ package hosts import ( "net" + "strings" "sync" "github.com/go-gost/gost/pkg/logger" @@ -61,24 +62,33 @@ func (h *Hosts) Map(ip net.IP, hostname string, aliases ...string) { // Lookup searches the IP address corresponds to the given network and host from the host table. // The network should be 'ip', 'ip4' or 'ip6', default network is 'ip'. +// the host should be a hostname (example.org) or a hostname with dot prefix (.example.org). func (h *Hosts) Lookup(network, host string) (ips []net.IP, ok bool) { - if h == nil || host == "" { - return + m := h.lookup(host) + if m == nil { + m = h.lookup("." + host) + } + if m == nil { + s := host + for { + if index := strings.IndexByte(s, '.'); index > 0 { + m = h.lookup(s[index:]) + s = s[index+1:] + if m == nil { + continue + } + } + break + } } - v, ok := h.mappings.Load(host) - if !ok { - return - } - m, _ := v.(*hostMapping) if m == nil { return } // hostname alias - if host != m.Hostname { - v, _ = h.mappings.Load(m.Hostname) - m, _ = v.(*hostMapping) + if !strings.HasPrefix(m.Hostname, ".") && host != m.Hostname { + m = h.lookup(m.Hostname) if m == nil { return } @@ -107,3 +117,16 @@ func (h *Hosts) Lookup(network, host string) (ips []net.IP, ok bool) { return } + +func (h *Hosts) lookup(host string) *hostMapping { + if h == nil || host == "" { + return nil + } + + v, ok := h.mappings.Load(host) + if !ok { + return nil + } + m, _ := v.(*hostMapping) + return m +}