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 // +build darwin freebsd linux netbsd openbsd
6
7 // Read system DNS config from /etc/resolv.conf
8
9 package net
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 // See resolv.conf(5) on a Linux machine.
21 // TODO(rsc): Supposed to call uname() and chop the beginning
22 // of the host name to get the default search domain.
23 // We assume it's in resolv.conf anyway.
24 func dnsReadConfig() (*dnsConfig, error) {
25 file, err := open("/etc/resolv.conf")
26 if err != nil {
27 return nil, &DNSConfigError{err}
28 }
29 conf := new(dnsConfig)
30 conf.servers = make([]string, 3)[0:0] // small, but the standard limit
31 conf.search = make([]string, 0)
32 conf.ndots = 1
33 conf.timeout = 5
34 conf.attempts = 2
35 conf.rotate = false
36 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
37 f := getFields(line)
38 if len(f) < 1 {
39 continue
40 }
41 switch f[0] {
42 case "nameserver": // add one name server
43 a := conf.servers
44 n := len(a)
45 if len(f) > 1 && n < cap(a) {
46 // One more check: make sure server name is
47 // just an IP address. Otherwise we need DNS
48 // to look it up.
49 name := f[1]
50 switch len(ParseIP(name)) {
51 case 16:
52 name = "[" + name + "]"
53 fallthrough
54 case 4:
55 a = a[0 : n+1]
56 a[n] = name
57 conf.servers = a
58 }
59 }
60
61 case "domain": // set search path to just this domain
62 if len(f) > 1 {
63 conf.search = make([]string, 1)
64 conf.search[0] = f[1]
65 } else {
66 conf.search = make([]string, 0)
67 }
68
69 case "search": // set search path to given servers
70 conf.search = make([]string, len(f)-1)
71 for i := 0; i < len(conf.search); i++ {
72 conf.search[i] = f[i+1]
73 }
74
75 case "options": // magic options
76 for i := 1; i < len(f); i++ {
77 s := f[i]
78 switch {
79 case len(s) >= 6 && s[0:6] == "ndots:":
80 n, _, _ := dtoi(s, 6)
81 if n < 1 {
82 n = 1
83 }
84 conf.ndots = n
85 case len(s) >= 8 && s[0:8] == "timeout:":
86 n, _, _ := dtoi(s, 8)
87 if n < 1 {
88 n = 1
89 }
90 conf.timeout = n
91 case len(s) >= 8 && s[0:9] == "attempts:":
92 n, _, _ := dtoi(s, 9)
93 if n < 1 {
94 n = 1
95 }
96 conf.attempts = n
97 case s == "rotate":
98 conf.rotate = true
99 }
100 }
101 }
102 }
103 file.close()
104
105 return conf, nil
106 }