The Go Programming Language

Source file src/pkg/net/dnsconfig.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	// Read system DNS config from /etc/resolv.conf
     6	
     7	package net
     8	
     9	import "os"
    10	
    11	type dnsConfig struct {
    12		servers  []string // servers to use
    13		search   []string // suffixes to append to local name
    14		ndots    int      // number of dots in name to trigger absolute lookup
    15		timeout  int      // seconds before giving up on packet
    16		attempts int      // lost packets before giving up on server
    17		rotate   bool     // round robin among servers
    18	}
    19	
    20	var dnsconfigError os.Error
    21	
    22	type DNSConfigError struct {
    23		Error os.Error
    24	}
    25	
    26	func (e *DNSConfigError) String() string {
    27		return "error reading DNS config: " + e.Error.String()
    28	}
    29	
    30	func (e *DNSConfigError) Timeout() bool   { return false }
    31	func (e *DNSConfigError) Temporary() bool { return false }
    32	
    33	// See resolv.conf(5) on a Linux machine.
    34	// TODO(rsc): Supposed to call uname() and chop the beginning
    35	// of the host name to get the default search domain.
    36	// We assume it's in resolv.conf anyway.
    37	func dnsReadConfig() (*dnsConfig, os.Error) {
    38		file, err := open("/etc/resolv.conf")
    39		if err != nil {
    40			return nil, &DNSConfigError{err}
    41		}
    42		conf := new(dnsConfig)
    43		conf.servers = make([]string, 3)[0:0] // small, but the standard limit
    44		conf.search = make([]string, 0)
    45		conf.ndots = 1
    46		conf.timeout = 5
    47		conf.attempts = 2
    48		conf.rotate = false
    49		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
    50			f := getFields(line)
    51			if len(f) < 1 {
    52				continue
    53			}
    54			switch f[0] {
    55			case "nameserver": // add one name server
    56				a := conf.servers
    57				n := len(a)
    58				if len(f) > 1 && n < cap(a) {
    59					// One more check: make sure server name is
    60					// just an IP address.  Otherwise we need DNS
    61					// to look it up.
    62					name := f[1]
    63					switch len(ParseIP(name)) {
    64					case 16:
    65						name = "[" + name + "]"
    66						fallthrough
    67					case 4:
    68						a = a[0 : n+1]
    69						a[n] = name
    70						conf.servers = a
    71					}
    72				}
    73	
    74			case "domain": // set search path to just this domain
    75				if len(f) > 1 {
    76					conf.search = make([]string, 1)
    77					conf.search[0] = f[1]
    78				} else {
    79					conf.search = make([]string, 0)
    80				}
    81	
    82			case "search": // set search path to given servers
    83				conf.search = make([]string, len(f)-1)
    84				for i := 0; i < len(conf.search); i++ {
    85					conf.search[i] = f[i+1]
    86				}
    87	
    88			case "options": // magic options
    89				for i := 1; i < len(f); i++ {
    90					s := f[i]
    91					switch {
    92					case len(s) >= 6 && s[0:6] == "ndots:":
    93						n, _, _ := dtoi(s, 6)
    94						if n < 1 {
    95							n = 1
    96						}
    97						conf.ndots = n
    98					case len(s) >= 8 && s[0:8] == "timeout:":
    99						n, _, _ := dtoi(s, 8)
   100						if n < 1 {
   101							n = 1
   102						}
   103						conf.timeout = n
   104					case len(s) >= 8 && s[0:9] == "attempts:":
   105						n, _, _ := dtoi(s, 9)
   106						if n < 1 {
   107							n = 1
   108						}
   109						conf.attempts = n
   110					case s == "rotate":
   111						conf.rotate = true
   112					}
   113				}
   114			}
   115		}
   116		file.close()
   117	
   118		return conf, nil
   119	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.