github.com/shijuvar/go@v0.0.0-20141209052335-e8f13700b70c/src/net/dnsclient.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 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 126 last := byte('.') 127 ok := false // Ok once we've seen a letter. 128 partlen := 0 129 for i := 0; i < len(s); i++ { 130 c := s[i] 131 switch { 132 default: 133 return false 134 case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': 135 ok = true 136 partlen++ 137 case '0' <= c && c <= '9': 138 // fine 139 partlen++ 140 case c == '-': 141 // Byte before dash cannot be dot. 142 if last == '.' { 143 return false 144 } 145 partlen++ 146 case c == '.': 147 // Byte before dot cannot be dot, dash. 148 if last == '.' || last == '-' { 149 return false 150 } 151 if partlen > 63 || partlen == 0 { 152 return false 153 } 154 partlen = 0 155 } 156 last = c 157 } 158 if last == '-' || partlen > 63 { 159 return false 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) 195 for i := range addrs { 196 s += int(addrs[i].Weight) 197 if s > n { 198 if i > 0 { 199 addrs[0], addrs[i] = addrs[i], addrs[0] 200 } 201 break 202 } 203 } 204 sum -= int(addrs[0].Weight) 205 addrs = addrs[1:] 206 } 207 } 208 209 // sort reorders SRV records as specified in RFC 2782. 210 func (addrs byPriorityWeight) sort() { 211 sort.Sort(addrs) 212 i := 0 213 for j := 1; j < len(addrs); j++ { 214 if addrs[i].Priority != addrs[j].Priority { 215 addrs[i:j].shuffleByWeight() 216 i = j 217 } 218 } 219 addrs[i:].shuffleByWeight() 220 } 221 222 // An MX represents a single DNS MX record. 223 type MX struct { 224 Host string 225 Pref uint16 226 } 227 228 // byPref implements sort.Interface to sort MX records by preference 229 type byPref []*MX 230 231 func (s byPref) Len() int { return len(s) } 232 233 func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref } 234 235 func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 236 237 // sort reorders MX records as specified in RFC 5321. 238 func (s byPref) sort() { 239 for i := range s { 240 j := rand.Intn(i + 1) 241 s[i], s[j] = s[j], s[i] 242 } 243 sort.Sort(s) 244 } 245 246 // An NS represents a single DNS NS record. 247 type NS struct { 248 Host string 249 }