github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/net/dnsconfig_unix.go (about) 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 dragonfly freebsd linux netbsd openbsd solaris 6 7 // Read system DNS config from /etc/resolv.conf 8 9 package net 10 11 var defaultNS = []string{"127.0.0.1", "::1"} 12 13 type dnsConfig struct { 14 servers []string // servers to use 15 search []string // suffixes to append to local name 16 ndots int // number of dots in name to trigger absolute lookup 17 timeout int // seconds before giving up on packet 18 attempts int // lost packets before giving up on server 19 rotate bool // round robin among servers 20 unknownOpt bool // anything unknown was encountered 21 lookup []string // OpenBSD top-level database "lookup" order 22 err error // any error that occurs during open of resolv.conf 23 } 24 25 // See resolv.conf(5) on a Linux machine. 26 // TODO(rsc): Supposed to call uname() and chop the beginning 27 // of the host name to get the default search domain. 28 func dnsReadConfig(filename string) *dnsConfig { 29 conf := &dnsConfig{ 30 ndots: 1, 31 timeout: 5, 32 attempts: 2, 33 } 34 file, err := open(filename) 35 if err != nil { 36 conf.servers = defaultNS 37 conf.err = err 38 return conf 39 } 40 defer file.close() 41 for line, ok := file.readLine(); ok; line, ok = file.readLine() { 42 if len(line) > 0 && (line[0] == ';' || line[0] == '#') { 43 // comment. 44 continue 45 } 46 f := getFields(line) 47 if len(f) < 1 { 48 continue 49 } 50 switch f[0] { 51 case "nameserver": // add one name server 52 if len(f) > 1 && len(conf.servers) < 3 { // small, but the standard limit 53 // One more check: make sure server name is 54 // just an IP address. Otherwise we need DNS 55 // to look it up. 56 if parseIPv4(f[1]) != nil { 57 conf.servers = append(conf.servers, f[1]) 58 } else if ip, _ := parseIPv6(f[1], true); ip != nil { 59 conf.servers = append(conf.servers, f[1]) 60 } 61 } 62 63 case "domain": // set search path to just this domain 64 if len(f) > 1 { 65 conf.search = []string{f[1]} 66 } 67 68 case "search": // set search path to given servers 69 conf.search = make([]string, len(f)-1) 70 for i := 0; i < len(conf.search); i++ { 71 conf.search[i] = f[i+1] 72 } 73 74 case "options": // magic options 75 for _, s := range f[1:] { 76 switch { 77 case hasPrefix(s, "ndots:"): 78 n, _, _ := dtoi(s, 6) 79 if n < 1 { 80 n = 1 81 } 82 conf.ndots = n 83 case hasPrefix(s, "timeout:"): 84 n, _, _ := dtoi(s, 8) 85 if n < 1 { 86 n = 1 87 } 88 conf.timeout = n 89 case hasPrefix(s, "attempts:"): 90 n, _, _ := dtoi(s, 9) 91 if n < 1 { 92 n = 1 93 } 94 conf.attempts = n 95 case s == "rotate": 96 conf.rotate = true 97 default: 98 conf.unknownOpt = true 99 } 100 } 101 102 case "lookup": 103 // OpenBSD option: 104 // http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/resolv.conf.5 105 // "the legal space-separated values are: bind, file, yp" 106 conf.lookup = f[1:] 107 108 default: 109 conf.unknownOpt = true 110 } 111 } 112 if len(conf.servers) == 0 { 113 conf.servers = defaultNS 114 } 115 return conf 116 } 117 118 func hasPrefix(s, prefix string) bool { 119 return len(s) >= len(prefix) && s[:len(prefix)] == prefix 120 }