]> Cypherpunks repositories - gostls13.git/commitdiff
net: implement windows LookupMX and LookupAddr
authorAlex Brainman <alex.brainman@gmail.com>
Fri, 5 Aug 2011 00:27:51 +0000 (10:27 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Fri, 5 Aug 2011 00:27:51 +0000 (10:27 +1000)
Also sort SRV records before returning from LookupSRV.

R=rsc
CC=golang-dev
https://golang.org/cl/4817049

src/pkg/net/dnsclient.go
src/pkg/net/lookup_test.go [moved from src/pkg/net/srv_test.go with 53% similarity]
src/pkg/net/lookup_unix.go
src/pkg/net/lookup_windows.go
src/pkg/syscall/ztypes_windows.go

index 280b19453e545d1d62f8d33fbc532c5186c26c78..93c04f6b590c32be4997634aff7d1ac974941bf1 100644 (file)
@@ -9,6 +9,7 @@ import (
        "fmt"
        "os"
        "rand"
+       "sort"
 )
 
 // DNSError represents a DNS lookup error.
@@ -182,9 +183,9 @@ func (s byPriorityWeight) Less(i, j int) bool {
                (s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
 }
 
-// shuffleSRVByWeight shuffles SRV records by weight using the algorithm
+// shuffleByWeight shuffles SRV records by weight using the algorithm
 // described in RFC 2782.  
-func shuffleSRVByWeight(addrs []*SRV) {
+func (addrs byPriorityWeight) shuffleByWeight() {
        sum := 0
        for _, addr := range addrs {
                sum += int(addr.Weight)
@@ -208,6 +209,19 @@ func shuffleSRVByWeight(addrs []*SRV) {
        }
 }
 
+// sort reorders SRV records as specified in RFC 2782.
+func (addrs byPriorityWeight) sort() {
+       sort.Sort(addrs)
+       i := 0
+       for j := 1; j < len(addrs); j++ {
+               if addrs[i].Priority != addrs[j].Priority {
+                       addrs[i:j].shuffleByWeight()
+                       i = j
+               }
+       }
+       addrs[i:].shuffleByWeight()
+}
+
 // An MX represents a single DNS MX record.
 type MX struct {
        Host string
@@ -222,3 +236,12 @@ func (s byPref) Len() int { return len(s) }
 func (s byPref) Less(i, j int) bool { return s[i].Pref < s[j].Pref }
 
 func (s byPref) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// sort reorders MX records as specified in RFC 5321.
+func (s byPref) sort() {
+       for i := range s {
+               j := rand.Intn(i + 1)
+               s[i], s[j] = s[j], s[i]
+       }
+       sort.Sort(s)
+}
similarity index 53%
rename from src/pkg/net/srv_test.go
rename to src/pkg/net/lookup_test.go
index f1c7a0ab498e20075679a112781d3ef5b493b8f5..995ab03d090d5bf9394349d1877f1b134691b0df 100644 (file)
@@ -27,3 +27,31 @@ func TestGoogleSRV(t *testing.T) {
                t.Errorf("no results")
        }
 }
+
+func TestGmailMX(t *testing.T) {
+       if testing.Short() || avoidMacFirewall {
+               t.Logf("skipping test to avoid external network")
+               return
+       }
+       mx, err := LookupMX("gmail.com")
+       if err != nil {
+               t.Errorf("failed: %s", err)
+       }
+       if len(mx) == 0 {
+               t.Errorf("no results")
+       }
+}
+
+func TestGoogleDNSAddr(t *testing.T) {
+       if testing.Short() || avoidMacFirewall {
+               t.Logf("skipping test to avoid external network")
+               return
+       }
+       names, err := LookupAddr("8.8.8.8")
+       if err != nil {
+               t.Errorf("failed: %s", err)
+       }
+       if len(names) == 0 {
+               t.Errorf("no results")
+       }
+}
index 168d3fa6d4b9d459061363386091f28aa9e02bb8..8f5e66212b3007c0cc8247b81e5ed069590ece81 100644 (file)
@@ -6,8 +6,6 @@ package net
 
 import (
        "os"
-       "rand"
-       "sort"
 )
 
 // LookupHost looks up the given host using the local resolver.
@@ -68,15 +66,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
                r := rr.(*dnsRR_SRV)
                addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
        }
-       sort.Sort(byPriorityWeight(addrs))
-       i := 0
-       for j := 1; j < len(addrs); j++ {
-               if addrs[i].Priority != addrs[j].Priority {
-                       shuffleSRVByWeight(addrs[i:j])
-                       i = j
-               }
-       }
-       shuffleSRVByWeight(addrs[i:len(addrs)])
+       byPriorityWeight(addrs).sort()
        return
 }
 
@@ -91,12 +81,7 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
                r := rr[i].(*dnsRR_MX)
                mx[i] = &MX{r.Mx, r.Pref}
        }
-       // Shuffle the records to match RFC 5321 when sorted
-       for i := range mx {
-               j := rand.Intn(i + 1)
-               mx[i], mx[j] = mx[j], mx[i]
-       }
-       sort.Sort(byPref(mx))
+       byPref(mx).sort()
        return
 }
 
index 16b37f56cbca06c7f1e72fb539fc84b83708a83f..fa3ad7c7f42b9949eccd688cbfac5ed9a7ee8315 100644 (file)
@@ -85,23 +85,46 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
                return "", nil, os.NewSyscallError("LookupSRV", int(e))
        }
        defer syscall.DnsRecordListFree(r, 1)
-       addrs = make([]*SRV, 100)
-       i := 0
+       addrs = make([]*SRV, 0, 10)
        for p := r; p != nil && p.Type == syscall.DNS_TYPE_SRV; p = p.Next {
                v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
-               addrs[i] = &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight}
-               i++
+               addrs = append(addrs, &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight})
        }
-       addrs = addrs[0:i]
+       byPriorityWeight(addrs).sort()
        return name, addrs, nil
 }
 
-// TODO(brainman): implement LookupMX and LookupAddr.
-
 func LookupMX(name string) (mx []*MX, err os.Error) {
-       return nil, os.NewSyscallError("LookupMX", syscall.EWINDOWS)
+       var r *syscall.DNSRecord
+       e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
+       if int(e) != 0 {
+               return nil, os.NewSyscallError("LookupMX", int(e))
+       }
+       defer syscall.DnsRecordListFree(r, 1)
+       mx = make([]*MX, 0, 10)
+       for p := r; p != nil && p.Type == syscall.DNS_TYPE_MX; p = p.Next {
+               v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
+               mx = append(mx, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]) + ".", v.Preference})
+       }
+       byPref(mx).sort()
+       return mx, nil
 }
 
 func LookupAddr(addr string) (name []string, err os.Error) {
-       return nil, os.NewSyscallError("LookupAddr", syscall.EWINDOWS)
+       arpa, err := reverseaddr(addr)
+       if err != nil {
+               return nil, err
+       }
+       var r *syscall.DNSRecord
+       e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
+       if int(e) != 0 {
+               return nil, os.NewSyscallError("LookupAddr", int(e))
+       }
+       defer syscall.DnsRecordListFree(r, 1)
+       name = make([]string, 0, 10)
+       for p := r; p != nil && p.Type == syscall.DNS_TYPE_PTR; p = p.Next {
+               v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
+               name = append(name, syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))
+       }
+       return name, nil
 }
index 10780f7672f230a0b63e0d6882b8d8099a8e6ea0..07f2b85f07702f09fec232cf5884af81d399c54b 100644 (file)
@@ -478,6 +478,12 @@ type DNSPTRData struct {
        Host *uint16
 }
 
+type DNSMXData struct {
+       NameExchange *uint16
+       Preference   uint16
+       Pad          uint16
+}
+
 type DNSRecord struct {
        Next     *DNSRecord
        Name     *uint16