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