blob: 26f0e04e907afc537d606a957cafb12e8446cb39 [file] [log] [blame]
Russ Cox83348f92008-12-18 15:42:39 -08001// 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
7package net
8
Russ Cox20011bc2009-09-17 10:27:04 -07009import "os"
Russ Cox83348f92008-12-18 15:42:39 -080010
Russ Cox47a05332010-04-26 22:15:25 -070011type dnsConfig struct {
Robert Griesemera3d10452009-12-15 15:35:38 -080012 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
Russ Cox83348f92008-12-18 15:42:39 -080018}
19
Russ Cox47a05332010-04-26 22:15:25 -070020var dnsconfigError os.Error
21
22type DNSConfigError struct {
23 Error os.Error
24}
25
26func (e *DNSConfigError) String() string {
27 return "error reading DNS config: " + e.Error.String()
28}
29
30func (e *DNSConfigError) Timeout() bool { return false }
31func (e *DNSConfigError) Temporary() bool { return false }
32
Russ Coxc93da7c72009-03-05 15:48:12 -080033
Russ Cox83348f92008-12-18 15:42:39 -080034// See resolv.conf(5) on a Linux machine.
35// TODO(rsc): Supposed to call uname() and chop the beginning
36// of the host name to get the default search domain.
37// We assume it's in resolv.conf anyway.
Russ Cox47a05332010-04-26 22:15:25 -070038func dnsReadConfig() (*dnsConfig, os.Error) {
Robert Griesemera3d10452009-12-15 15:35:38 -080039 file, err := open("/etc/resolv.conf")
Russ Coxc93da7c72009-03-05 15:48:12 -080040 if err != nil {
Russ Cox47a05332010-04-26 22:15:25 -070041 return nil, &DNSConfigError{err}
Russ Cox83348f92008-12-18 15:42:39 -080042 }
Russ Cox47a05332010-04-26 22:15:25 -070043 conf := new(dnsConfig)
Robert Griesemera3d10452009-12-15 15:35:38 -080044 conf.servers = make([]string, 3)[0:0] // small, but the standard limit
45 conf.search = make([]string, 0)
46 conf.ndots = 1
Stephen Mab73e5922010-03-03 15:25:26 +110047 conf.timeout = 5
48 conf.attempts = 2
Robert Griesemera3d10452009-12-15 15:35:38 -080049 conf.rotate = false
Russ Coxd8921c52009-02-15 14:18:39 -080050 for line, ok := file.readLine(); ok; line, ok = file.readLine() {
Robert Griesemera3d10452009-12-15 15:35:38 -080051 f := getFields(line)
Russ Cox83348f92008-12-18 15:42:39 -080052 if len(f) < 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -080053 continue
Russ Cox83348f92008-12-18 15:42:39 -080054 }
55 switch f[0] {
Robert Griesemera3d10452009-12-15 15:35:38 -080056 case "nameserver": // add one name server
57 a := conf.servers
58 n := len(a)
Russ Cox83348f92008-12-18 15:42:39 -080059 if len(f) > 1 && n < cap(a) {
60 // One more check: make sure server name is
61 // just an IP address. Otherwise we need DNS
62 // to look it up.
Robert Griesemera3d10452009-12-15 15:35:38 -080063 name := f[1]
Russ Coxe53f7d82010-03-03 17:30:39 -080064 switch len(ParseIP(name)) {
65 case 16:
66 name = "[" + name + "]"
67 fallthrough
68 case 4:
Robert Griesemera3d10452009-12-15 15:35:38 -080069 a = a[0 : n+1]
70 a[n] = name
71 conf.servers = a
Russ Cox83348f92008-12-18 15:42:39 -080072 }
73 }
74
Robert Griesemera3d10452009-12-15 15:35:38 -080075 case "domain": // set search path to just this domain
Russ Cox83348f92008-12-18 15:42:39 -080076 if len(f) > 1 {
Robert Griesemera3d10452009-12-15 15:35:38 -080077 conf.search = make([]string, 1)
78 conf.search[0] = f[1]
Russ Cox83348f92008-12-18 15:42:39 -080079 } else {
Robert Griesemer40621d52009-11-09 12:07:39 -080080 conf.search = make([]string, 0)
Russ Cox83348f92008-12-18 15:42:39 -080081 }
82
Robert Griesemera3d10452009-12-15 15:35:38 -080083 case "search": // set search path to given servers
84 conf.search = make([]string, len(f)-1)
Russ Cox83348f92008-12-18 15:42:39 -080085 for i := 0; i < len(conf.search); i++ {
Robert Griesemer40621d52009-11-09 12:07:39 -080086 conf.search[i] = f[i+1]
Russ Cox83348f92008-12-18 15:42:39 -080087 }
88
Robert Griesemera3d10452009-12-15 15:35:38 -080089 case "options": // magic options
Russ Cox83348f92008-12-18 15:42:39 -080090 for i := 1; i < len(f); i++ {
Robert Griesemera3d10452009-12-15 15:35:38 -080091 s := f[i]
Russ Cox83348f92008-12-18 15:42:39 -080092 switch {
93 case len(s) >= 6 && s[0:6] == "ndots:":
Robert Griesemera3d10452009-12-15 15:35:38 -080094 n, _, _ := dtoi(s, 6)
Russ Cox83348f92008-12-18 15:42:39 -080095 if n < 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -080096 n = 1
Russ Cox83348f92008-12-18 15:42:39 -080097 }
Robert Griesemera3d10452009-12-15 15:35:38 -080098 conf.ndots = n
Russ Cox83348f92008-12-18 15:42:39 -080099 case len(s) >= 8 && s[0:8] == "timeout:":
Robert Griesemera3d10452009-12-15 15:35:38 -0800100 n, _, _ := dtoi(s, 8)
Russ Cox83348f92008-12-18 15:42:39 -0800101 if n < 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800102 n = 1
Russ Cox83348f92008-12-18 15:42:39 -0800103 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800104 conf.timeout = n
Russ Cox83348f92008-12-18 15:42:39 -0800105 case len(s) >= 8 && s[0:9] == "attempts:":
Robert Griesemera3d10452009-12-15 15:35:38 -0800106 n, _, _ := dtoi(s, 9)
Russ Cox83348f92008-12-18 15:42:39 -0800107 if n < 1 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800108 n = 1
Russ Cox83348f92008-12-18 15:42:39 -0800109 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800110 conf.attempts = n
Russ Cox83348f92008-12-18 15:42:39 -0800111 case s == "rotate":
Robert Griesemer40621d52009-11-09 12:07:39 -0800112 conf.rotate = true
Russ Cox83348f92008-12-18 15:42:39 -0800113 }
114 }
115 }
116 }
Robert Griesemera3d10452009-12-15 15:35:38 -0800117 file.close()
Russ Cox83348f92008-12-18 15:42:39 -0800118
Robert Griesemera3d10452009-12-15 15:35:38 -0800119 return conf, nil
Russ Cox83348f92008-12-18 15:42:39 -0800120}