break
}
}
- return []string{absDomainName(b)}, nil
+ return []string{absDomainName(string(b))}, nil
}
func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *C.struct_sockaddr, salen C.socklen_t) {
package net
import (
+ "internal/bytealg"
"internal/itoa"
"sort"
// It's hard to tell so we settle on the heuristic that names without dots
// (like "localhost" or "myhost") do not get trailing dots, but any other
// names do.
-func absDomainName(b []byte) string {
- hasDots := false
- for _, x := range b {
- if x == '.' {
- hasDots = true
- break
- }
- }
- if hasDots && b[len(b)-1] != '.' {
- b = append(b, '.')
+func absDomainName(s string) string {
+ if bytealg.IndexByteString(s, '.') != -1 && s[len(s)-1] != '.' {
+ s += "."
}
- return string(b)
+ return s
}
// An SRV represents a single DNS SRV record.
continue
}
for i := 1; i < len(f); i++ {
- name := absDomainName([]byte(f[i]))
+ name := absDomainName(f[i])
h := []byte(f[i])
lowerASCIIBytes(h)
- key := absDomainName(h)
+ key := absDomainName(string(h))
hs[key] = append(hs[key], addr)
is[addr] = append(is[addr], name)
}
defer hosts.Unlock()
readHosts()
if len(hosts.byName) != 0 {
- // TODO(jbd,bradfitz): avoid this alloc if host is already all lowercase?
- // or linear scan the byName map if it's small enough?
- lowerHost := []byte(host)
- lowerASCIIBytes(lowerHost)
- if ips, ok := hosts.byName[absDomainName(lowerHost)]; ok {
+ if hasUpperCase(host) {
+ lowerHost := []byte(host)
+ lowerASCIIBytes(lowerHost)
+ host = string(lowerHost)
+ }
+ if ips, ok := hosts.byName[absDomainName(host)]; ok {
ipsCp := make([]string, len(ips))
copy(ipsCp, ips)
return ipsCp
}
func testStaticHost(t *testing.T, hostsPath string, ent staticHostEntry) {
- ins := []string{ent.in, absDomainName([]byte(ent.in)), strings.ToLower(ent.in), strings.ToUpper(ent.in)}
+ ins := []string{ent.in, absDomainName(ent.in), strings.ToLower(ent.in), strings.ToUpper(ent.in)}
for _, in := range ins {
addrs := lookupStaticHost(in)
if !reflect.DeepEqual(addrs, ent.out) {
func testStaticAddr(t *testing.T, hostsPath string, ent staticHostEntry) {
hosts := lookupStaticAddr(ent.in)
for i := range ent.out {
- ent.out[i] = absDomainName([]byte(ent.out[i]))
+ ent.out[i] = absDomainName(ent.out[i])
}
if !reflect.DeepEqual(hosts, ent.out) {
t.Errorf("%s, lookupStaticAddr(%s) = %v; want %v", hostsPath, ent.in, hosts, ent.out)
if !(portOk && priorityOk && weightOk) {
continue
}
- addrs = append(addrs, &SRV{absDomainName([]byte(f[5])), uint16(port), uint16(priority), uint16(weight)})
- cname = absDomainName([]byte(f[0]))
+ addrs = append(addrs, &SRV{absDomainName(f[5]), uint16(port), uint16(priority), uint16(weight)})
+ cname = absDomainName(f[0])
}
byPriorityWeight(addrs).sort()
return
continue
}
if pref, _, ok := dtoi(f[2]); ok {
- mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)})
+ mx = append(mx, &MX{absDomainName(f[3]), uint16(pref)})
}
}
byPref(mx).sort()
if len(f) < 3 {
continue
}
- ns = append(ns, &NS{absDomainName([]byte(f[2]))})
+ ns = append(ns, &NS{absDomainName(f[2])})
}
return
}
if len(f) < 3 {
continue
}
- name = append(name, absDomainName([]byte(f[2])))
+ name = append(name, absDomainName(f[2]))
}
return
}
// windows returns DNS_INFO_NO_RECORDS if there are no CNAME-s
if errno, ok := e.(syscall.Errno); ok && errno == syscall.DNS_INFO_NO_RECORDS {
// if there are no aliases, the canonical name is the input name
- return absDomainName([]byte(name)), nil
+ return absDomainName(name), nil
}
if e != nil {
return "", &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
resolved := resolveCNAME(syscall.StringToUTF16Ptr(name), r)
cname := windows.UTF16PtrToString(resolved)
- return absDomainName([]byte(cname)), nil
+ return absDomainName(cname), nil
}
func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
srvs := make([]*SRV, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_SRV, target) {
v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
- srvs = append(srvs, &SRV{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]))), v.Port, v.Priority, v.Weight})
+ srvs = append(srvs, &SRV{absDomainName(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:])), v.Port, v.Priority, v.Weight})
}
byPriorityWeight(srvs).sort()
- return absDomainName([]byte(target)), srvs, nil
+ return absDomainName(target), srvs, nil
}
func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
mxs := make([]*MX, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_MX, name) {
v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
- mxs = append(mxs, &MX{absDomainName([]byte(windows.UTF16PtrToString(v.NameExchange))), v.Preference})
+ mxs = append(mxs, &MX{absDomainName(windows.UTF16PtrToString(v.NameExchange)), v.Preference})
}
byPref(mxs).sort()
return mxs, nil
nss := make([]*NS, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_NS, name) {
v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
- nss = append(nss, &NS{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:])))})
+ nss = append(nss, &NS{absDomainName(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))})
}
return nss, nil
}
ptrs := make([]string, 0, 10)
for _, p := range validRecs(r, syscall.DNS_TYPE_PTR, arpa) {
v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
- ptrs = append(ptrs, absDomainName([]byte(windows.UTF16PtrToString(v.Host))))
+ ptrs = append(ptrs, absDomainName(windows.UTF16PtrToString(v.Host)))
}
return ptrs, nil
}
rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+mail exchanger\s*=\s*([0-9]+)\s*([a-z0-9.\-]+)$`)
for _, ans := range rx.FindAllStringSubmatch(r, -1) {
pref, _, _ := dtoi(ans[2])
- mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)})
+ mx = append(mx, &MX{absDomainName(ans[3]), uint16(pref)})
}
// windows nslookup syntax
// gmail.com MX preference = 30, mail exchanger = alt3.gmail-smtp-in.l.google.com
rx = regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+MX preference\s*=\s*([0-9]+)\s*,\s*mail exchanger\s*=\s*([a-z0-9.\-]+)$`)
for _, ans := range rx.FindAllStringSubmatch(r, -1) {
pref, _, _ := dtoi(ans[2])
- mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)})
+ mx = append(mx, &MX{absDomainName(ans[3]), uint16(pref)})
}
return
}
// golang.org nameserver = ns1.google.com.
rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+nameserver\s*=\s*([a-z0-9.\-]+)$`)
for _, ans := range rx.FindAllStringSubmatch(r, -1) {
- ns = append(ns, &NS{absDomainName([]byte(ans[2]))})
+ ns = append(ns, &NS{absDomainName(ans[2])})
}
return
}
for _, ans := range rx.FindAllStringSubmatch(r, -1) {
last = ans[2]
}
- return absDomainName([]byte(last)), nil
+ return absDomainName(last), nil
}
func nslookupTXT(name string) (txt []string, err error) {
ptr = make([]string, 0, 10)
rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`)
for _, ans := range rx.FindAllStringSubmatch(r, -1) {
- ptr = append(ptr, absDomainName([]byte(ans[1])))
+ ptr = append(ptr, absDomainName(ans[1]))
}
return
}
return i
}
+// hasUpperCase tells whether the given string contains at least one upper-case.
+func hasUpperCase(s string) bool {
+ for i := range s {
+ if 'A' <= s[i] && s[i] <= 'Z' {
+ return true
+ }
+ }
+ return false
+}
+
// lowerASCIIBytes makes x ASCII lowercase in-place.
func lowerASCIIBytes(x []byte) {
for i, b := range x {