...
Source file
src/net/dnsconfig_unix.go
Documentation: net
1
2
3
4
5
6
7
8
9 package net
10
11 import (
12 "os"
13 "sync/atomic"
14 "time"
15 )
16
17 var (
18 defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
19 getHostname = os.Hostname
20 )
21
22 type dnsConfig struct {
23 servers []string
24 search []string
25 ndots int
26 timeout time.Duration
27 attempts int
28 rotate bool
29 unknownOpt bool
30 lookup []string
31 err error
32 mtime time.Time
33 soffset uint32
34 }
35
36
37 func dnsReadConfig(filename string) *dnsConfig {
38 conf := &dnsConfig{
39 ndots: 1,
40 timeout: 5 * time.Second,
41 attempts: 2,
42 }
43 file, err := open(filename)
44 if err != nil {
45 conf.servers = defaultNS
46 conf.search = dnsDefaultSearch()
47 conf.err = err
48 return conf
49 }
50 defer file.close()
51 if fi, err := file.file.Stat(); err == nil {
52 conf.mtime = fi.ModTime()
53 } else {
54 conf.servers = defaultNS
55 conf.search = dnsDefaultSearch()
56 conf.err = err
57 return conf
58 }
59 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
60 if len(line) > 0 && (line[0] == ';' || line[0] == '#') {
61
62 continue
63 }
64 f := getFields(line)
65 if len(f) < 1 {
66 continue
67 }
68 switch f[0] {
69 case "nameserver":
70 if len(f) > 1 && len(conf.servers) < 3 {
71
72
73
74 if parseIPv4(f[1]) != nil {
75 conf.servers = append(conf.servers, JoinHostPort(f[1], "53"))
76 } else if ip, _ := parseIPv6(f[1], true); ip != nil {
77 conf.servers = append(conf.servers, JoinHostPort(f[1], "53"))
78 }
79 }
80
81 case "domain":
82 if len(f) > 1 {
83 conf.search = []string{ensureRooted(f[1])}
84 }
85
86 case "search":
87 conf.search = make([]string, len(f)-1)
88 for i := 0; i < len(conf.search); i++ {
89 conf.search[i] = ensureRooted(f[i+1])
90 }
91
92 case "options":
93 for _, s := range f[1:] {
94 switch {
95 case hasPrefix(s, "ndots:"):
96 n, _, _ := dtoi(s[6:])
97 if n < 0 {
98 n = 0
99 } else if n > 15 {
100 n = 15
101 }
102 conf.ndots = n
103 case hasPrefix(s, "timeout:"):
104 n, _, _ := dtoi(s[8:])
105 if n < 1 {
106 n = 1
107 }
108 conf.timeout = time.Duration(n) * time.Second
109 case hasPrefix(s, "attempts:"):
110 n, _, _ := dtoi(s[9:])
111 if n < 1 {
112 n = 1
113 }
114 conf.attempts = n
115 case s == "rotate":
116 conf.rotate = true
117 default:
118 conf.unknownOpt = true
119 }
120 }
121
122 case "lookup":
123
124
125
126 conf.lookup = f[1:]
127
128 default:
129 conf.unknownOpt = true
130 }
131 }
132 if len(conf.servers) == 0 {
133 conf.servers = defaultNS
134 }
135 if len(conf.search) == 0 {
136 conf.search = dnsDefaultSearch()
137 }
138 return conf
139 }
140
141
142
143
144
145 func (c *dnsConfig) serverOffset() uint32 {
146 if c.rotate {
147 return atomic.AddUint32(&c.soffset, 1) - 1
148 }
149 return 0
150 }
151
152 func dnsDefaultSearch() []string {
153 hn, err := getHostname()
154 if err != nil {
155
156 return nil
157 }
158 if i := byteIndex(hn, '.'); i >= 0 && i < len(hn)-1 {
159 return []string{ensureRooted(hn[i+1:])}
160 }
161 return nil
162 }
163
164 func hasPrefix(s, prefix string) bool {
165 return len(s) >= len(prefix) && s[:len(prefix)] == prefix
166 }
167
168 func ensureRooted(s string) string {
169 if len(s) > 0 && s[len(s)-1] == '.' {
170 return s
171 }
172 return s + "."
173 }
174
View as plain text