github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/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. 51 return "", nil, &DNSError{Err: "server misbehaving", Name: name, Server: server} 52 } 53 54 // Look for the name. 55 // Presotto says it's okay to assume that servers listed in 56 // /etc/resolv.conf are recursive resolvers. 57 // We asked for recursion, so it should have included 58 // all the answers we need in this one packet. 59 Cname: 60 for cnameloop := 0; cnameloop < 10; cnameloop++ { 61 addrs = addrs[0:0] 62 for _, rr := range dns.answer { 63 if _, justHeader := rr.(*dnsRR_Header); justHeader { 64 // Corrupt record: we only have a 65 // header. That header might say it's 66 // of type qtype, but we don't 67 // actually have it. Skip. 68 continue 69 } 70 h := rr.Header() 71 if h.Class == dnsClassINET && equalASCIILabel(h.Name, name) { 72 switch h.Rrtype { 73 case qtype: 74 addrs = append(addrs, rr) 75 case dnsTypeCNAME: 76 // redirect to cname 77 name = rr.(*dnsRR_CNAME).Cname 78 continue Cname 79 } 80 } 81 } 82 if len(addrs) == 0 { 83 return "", nil, &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server} 84 } 85 return name, addrs, nil 86 } 87 88 return "", nil, &DNSError{Err: "too many redirects", Name: name, Server: server} 89 } 90 91 func equalASCIILabel(x, y string) bool { 92 if len(x) != len(y) { 93 return false 94 } 95 for i := 0; i < len(x); i++ { 96 a := x[i] 97 b := y[i] 98 if 'A' <= a && a <= 'Z' { 99 a += 0x20 100 } 101 if 'A' <= b && b <= 'Z' { 102 b += 0x20 103 } 104 if a != b { 105 return false 106 } 107 } 108 return true 109 } 110 111 func isDomainName(s string) bool { 112 // See RFC 1035, RFC 3696. 113 if len(s) == 0 { 114 return false 115 } 116 if len(s) > 255 { 117 return false 118 } 119 120 last := byte('.') 121 ok := false // Ok once we've seen a letter. 122 partlen := 0 123 for i := 0; i < len(s); i++ { 124 c := s[i] 125 switch { 126 default: 127 return false 128 case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': 129 ok = true 130 partlen++ 131 case '0' <= c && c <= '9': 132 // fine 133 partlen++ 134 case c == '-': 135 // Byte before dash cannot be dot. 136 if last == '.' { 137 return false 138 } 139 partlen++ 140 case c == '.': 141 // Byte before dot cannot be dot, dash. 142 if last == '.' || last == '-' { 143 return false 144 } 145 if partlen > 63 || partlen == 0 { 146 return false 147 } 148 partlen = 0 149 } 150 last = c 151 } 152 if last == '-' || partlen > 63 { 153 return false 154 } 155 156 return ok 157 } 158 159 // An SRV represents a single DNS SRV record. 160 type SRV struct { 161 Target string 162 Port uint16 163 Priority uint16 164 Weight uint16 165 } 166 167 // byPriorityWeight sorts SRV records by ascending priority and weight. 168 type byPriorityWeight []*SRV 169 170 func (s byPriorityWeight) Len() int { return len(s) } 171 func (s byPriorityWeight) Less(i, j int) bool { 172 return s[i].Priority < s[j].Priority || (s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight) 173 } 174 func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 175 176 // shuffleByWeight shuffles SRV records by weight using the algorithm 177 // described in RFC 2782. 178 func (addrs byPriorityWeight) shuffleByWeight() { 179 sum := 0 180 for _, addr := range addrs { 181 sum += int(addr.Weight) 182 } 183 for sum > 0 && len(addrs) > 1 { 184 s := 0 185 n := rand.Intn(sum) 186 for i := range addrs { 187 s += int(addrs[i].Weight) 188 if s > n { 189 if i > 0 { 190 addrs[0], addrs[i] = addrs[i], addrs[0] 191 } 192 break 193 } 194 } 195 sum -= int(addrs[0].Weight) 196 addrs = addrs[1:] 197 } 198 } 199 200 // sort reorders SRV records as specified in RFC 2782. 201 func (addrs byPriorityWeight) sort() { 202 sort.Sort(addrs) 203 i := 0 204 for j := 1; j < len(addrs); j++ { 205 if addrs[i].Priority != addrs[j].Priority { 206 addrs[i:j].shuffleByWeight() 207 i = j 208 } 209 } 210 addrs[i:].shuffleByWeight() 211 } 212 213 // An MX represents a single DNS MX record. 214 type MX struct { 215 Host string 216 Pref uint16 217 } 218 219 // byPref implements sort.Interface to sort MX records by preference 220 type byPref []*MX 221 222 func (s byPref) Len() int { return len(s) } 223 func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref } 224 func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 225 226 // sort reorders MX records as specified in RFC 5321. 227 func (s byPref) sort() { 228 for i := range s { 229 j := rand.Intn(i + 1) 230 s[i], s[j] = s[j], s[i] 231 } 232 sort.Sort(s) 233 } 234 235 // An NS represents a single DNS NS record. 236 type NS struct { 237 Host string 238 }