...

Source file src/net/hosts.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package net
     6	
     7	import (
     8		"internal/bytealg"
     9		"sync"
    10		"time"
    11	)
    12	
    13	const cacheMaxAge = 5 * time.Second
    14	
    15	func parseLiteralIP(addr string) string {
    16		var ip IP
    17		var zone string
    18		ip = parseIPv4(addr)
    19		if ip == nil {
    20			ip, zone = parseIPv6Zone(addr)
    21		}
    22		if ip == nil {
    23			return ""
    24		}
    25		if zone == "" {
    26			return ip.String()
    27		}
    28		return ip.String() + "%" + zone
    29	}
    30	
    31	// hosts contains known host entries.
    32	var hosts struct {
    33		sync.Mutex
    34	
    35		// Key for the list of literal IP addresses must be a host
    36		// name. It would be part of DNS labels, a FQDN or an absolute
    37		// FQDN.
    38		// For now the key is converted to lower case for convenience.
    39		byName map[string][]string
    40	
    41		// Key for the list of host names must be a literal IP address
    42		// including IPv6 address with zone identifier.
    43		// We don't support old-classful IP address notation.
    44		byAddr map[string][]string
    45	
    46		expire time.Time
    47		path   string
    48		mtime  time.Time
    49		size   int64
    50	}
    51	
    52	func readHosts() {
    53		now := time.Now()
    54		hp := testHookHostsPath
    55	
    56		if now.Before(hosts.expire) && hosts.path == hp && len(hosts.byName) > 0 {
    57			return
    58		}
    59		mtime, size, err := stat(hp)
    60		if err == nil && hosts.path == hp && hosts.mtime.Equal(mtime) && hosts.size == size {
    61			hosts.expire = now.Add(cacheMaxAge)
    62			return
    63		}
    64	
    65		hs := make(map[string][]string)
    66		is := make(map[string][]string)
    67		var file *file
    68		if file, _ = open(hp); file == nil {
    69			return
    70		}
    71		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
    72			if i := bytealg.IndexByteString(line, '#'); i >= 0 {
    73				// Discard comments.
    74				line = line[0:i]
    75			}
    76			f := getFields(line)
    77			if len(f) < 2 {
    78				continue
    79			}
    80			addr := parseLiteralIP(f[0])
    81			if addr == "" {
    82				continue
    83			}
    84			for i := 1; i < len(f); i++ {
    85				name := absDomainName([]byte(f[i]))
    86				h := []byte(f[i])
    87				lowerASCIIBytes(h)
    88				key := absDomainName(h)
    89				hs[key] = append(hs[key], addr)
    90				is[addr] = append(is[addr], name)
    91			}
    92		}
    93		// Update the data cache.
    94		hosts.expire = now.Add(cacheMaxAge)
    95		hosts.path = hp
    96		hosts.byName = hs
    97		hosts.byAddr = is
    98		hosts.mtime = mtime
    99		hosts.size = size
   100		file.close()
   101	}
   102	
   103	// lookupStaticHost looks up the addresses for the given host from /etc/hosts.
   104	func lookupStaticHost(host string) []string {
   105		hosts.Lock()
   106		defer hosts.Unlock()
   107		readHosts()
   108		if len(hosts.byName) != 0 {
   109			// TODO(jbd,bradfitz): avoid this alloc if host is already all lowercase?
   110			// or linear scan the byName map if it's small enough?
   111			lowerHost := []byte(host)
   112			lowerASCIIBytes(lowerHost)
   113			if ips, ok := hosts.byName[absDomainName(lowerHost)]; ok {
   114				ipsCp := make([]string, len(ips))
   115				copy(ipsCp, ips)
   116				return ipsCp
   117			}
   118		}
   119		return nil
   120	}
   121	
   122	// lookupStaticAddr looks up the hosts for the given address from /etc/hosts.
   123	func lookupStaticAddr(addr string) []string {
   124		hosts.Lock()
   125		defer hosts.Unlock()
   126		readHosts()
   127		addr = parseLiteralIP(addr)
   128		if addr == "" {
   129			return nil
   130		}
   131		if len(hosts.byAddr) != 0 {
   132			if hosts, ok := hosts.byAddr[addr]; ok {
   133				hostsCp := make([]string, len(hosts))
   134				copy(hostsCp, hosts)
   135				return hostsCp
   136			}
   137		}
   138		return nil
   139	}
   140	

View as plain text