Source file src/pkg/net/dnsclient.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 package net 6 7 import ( 8 "math/rand" 9 "sort" 10 ) 11 12 // DNSError represents a DNS lookup error. 13 type DNSError struct { 14 Err string // description of the error 15 Name string // name looked for 16 Server string // server used 17 IsTimeout bool 18 } 19 20 func (e *DNSError) Error() string { 21 if e == nil { 22 return "<nil>" 23 } 24 s := "lookup " + e.Name 25 if e.Server != "" { 26 s += " on " + e.Server 27 } 28 s += ": " + e.Err 29 return s 30 } 31 32 func (e *DNSError) Timeout() bool { return e.IsTimeout } 33 func (e *DNSError) Temporary() bool { return e.IsTimeout } 34 35 const noSuchHost = "no such host" 36 37 // reverseaddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP 38 // address addr suitable for rDNS (PTR) record lookup or an error if it fails 39 // to parse the IP address. 40 func reverseaddr(addr string) (arpa string, err error) { 41 ip := ParseIP(addr) 42 if ip == nil { 43 return "", &DNSError{Err: "unrecognized address", Name: addr} 44 } 45 if ip.To4() != nil { 46 return itoa(int(ip[15])) + "." + itoa(int(ip[14])) + "." + itoa(int(ip[13])) + "." + 47 itoa(int(ip[12])) + ".in-addr.arpa.", nil 48 } 49 // Must be IPv6 50 buf := make([]byte, 0, len(ip)*4+len("ip6.arpa.")) 51 // Add it, in reverse, to the buffer 52 for i := len(ip) - 1; i >= 0; i-- { 53 v := ip[i] 54 buf = append(buf, hexDigit[v&0xF]) 55 buf = append(buf, '.') 56 buf = append(buf, hexDigit[v>>4]) 57 buf = append(buf, '.') 58 } 59 // Append "ip6.arpa." and return (buf already has the final .) 60 buf = append(buf, "ip6.arpa."...) 61 return string(buf), nil 62 } 63 64 // Find answer for name in dns message. 65 // On return, if err == nil, addrs != nil. 66 func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err error) { 67 addrs = make([]dnsRR, 0, len(dns.answer)) 68 69 if dns.rcode == dnsRcodeNameError && dns.recursion_available { 70 return "", nil, &DNSError{Err: noSuchHost, Name: name} 71 } 72 if dns.rcode != dnsRcodeSuccess { 73 // None of the error codes make sense 74 // for the query we sent. If we didn't get 75 // a name error and we didn't get success, 76 // the server is behaving incorrectly. 77 return "", nil, &DNSError{Err: "server misbehaving", Name: name, Server: server} 78 } 79 80 // Look for the name. 81 // Presotto says it's okay to assume that servers listed in 82 // /etc/resolv.conf are recursive resolvers. 83 // We asked for recursion, so it should have included 84 // all the answers we need in this one packet. 85 Cname: 86 for cnameloop := 0; cnameloop < 10; cnameloop++ { 87 addrs = addrs[0:0] 88 for _, rr := range dns.answer { 89 if _, justHeader := rr.(*dnsRR_Header); justHeader { 90 // Corrupt record: we only have a 91 // header. That header might say it's 92 // of type qtype, but we don't 93 // actually have it. Skip. 94 continue 95 } 96 h := rr.Header() 97 if h.Class == dnsClassINET && h.Name == name { 98 switch h.Rrtype { 99 case qtype: 100 addrs = append(addrs, rr) 101 case dnsTypeCNAME: 102 // redirect to cname 103 name = rr.(*dnsRR_CNAME).Cname 104 continue Cname 105 } 106 } 107 } 108 if len(addrs) == 0 { 109 return "", nil, &DNSError{Err: noSuchHost, Name: name, Server: server} 110 } 111 return name, addrs, nil 112 } 113 114 return "", nil, &DNSError{Err: "too many redirects", Name: name, Server: server} 115 } 116 117 func isDomainName(s string) bool { 118 // See RFC 1035, RFC 3696. 119 if len(s) == 0 { 120 return false 121 } 122 if len(s) > 255 { 123 return false 124 } 125 if s[len(s)-1] != '.' { // simplify checking loop: make name end in dot 126 s += "." 127 } 128 129 last := byte('.') 130 ok := false // ok once we've seen a letter 131 partlen := 0 132 for i := 0; i < len(s); i++ { 133 c := s[i] 134 switch { 135 default: 136 return false 137 case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': 138 ok = true 139 partlen++ 140 case '0' <= c && c <= '9': 141 // fine 142 partlen++ 143 case c == '-': 144 // byte before dash cannot be dot 145 if last == '.' { 146 return false 147 } 148 partlen++ 149 case c == '.': 150 // byte before dot cannot be dot, dash 151 if last == '.' || last == '-' { 152 return false 153 } 154 if partlen > 63 || partlen == 0 { 155 return false 156 } 157 partlen = 0 158 } 159 last = c 160 } 161 162 return ok 163 } 164 165 // An SRV represents a single DNS SRV record. 166 type SRV struct { 167 Target string 168 Port uint16 169 Priority uint16 170 Weight uint16 171 } 172 173 // byPriorityWeight sorts SRV records by ascending priority and weight. 174 type byPriorityWeight []*SRV 175 176 func (s byPriorityWeight) Len() int { return len(s) } 177 178 func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 179 180 func (s byPriorityWeight) Less(i, j int) bool { 181 return s[i].Priority < s[j].Priority || 182 (s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight) 183 } 184 185 // shuffleByWeight shuffles SRV records by weight using the algorithm 186 // described in RFC 2782. 187 func (addrs byPriorityWeight) shuffleByWeight() { 188 sum := 0 189 for _, addr := range addrs { 190 sum += int(addr.Weight) 191 } 192 for sum > 0 && len(addrs) > 1 { 193 s := 0 194 n := rand.Intn(sum + 1) 195 for i := range addrs { 196 s += int(addrs[i].Weight) 197 if s >= n { 198 if i > 0 { 199 t := addrs[i] 200 copy(addrs[1:i+1], addrs[0:i]) 201 addrs[0] = t 202 } 203 break 204 } 205 } 206 sum -= int(addrs[0].Weight) 207 addrs = addrs[1:] 208 } 209 } 210 211 // sort reorders SRV records as specified in RFC 2782. 212 func (addrs byPriorityWeight) sort() { 213 sort.Sort(addrs) 214 i := 0 215 for j := 1; j < len(addrs); j++ { 216 if addrs[i].Priority != addrs[j].Priority { 217 addrs[i:j].shuffleByWeight() 218 i = j 219 } 220 } 221 addrs[i:].shuffleByWeight() 222 } 223 224 // An MX represents a single DNS MX record. 225 type MX struct { 226 Host string 227 Pref uint16 228 } 229 230 // byPref implements sort.Interface to sort MX records by preference 231 type byPref []*MX 232 233 func (s byPref) Len() int { return len(s) } 234 235 func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref } 236 237 func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 238 239 // sort reorders MX records as specified in RFC 5321. 240 func (s byPref) sort() { 241 for i := range s { 242 j := rand.Intn(i + 1) 243 s[i], s[j] = s[j], s[i] 244 } 245 sort.Sort(s) 246 }