summaryrefslogtreecommitdiff
path: root/libgo/go/net
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-20 00:18:15 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-20 00:18:15 +0000
commit84911de8492fb75007eec6bfa4abb7905439f93c (patch)
treec891bdec1e6f073f73fedeef23718bc3ac30d499 /libgo/go/net
parentad33e6a8510b48571eaef50af339892925108830 (diff)
downloadgcc-84911de8492fb75007eec6bfa4abb7905439f93c.tar.gz
Update to current version of Go library.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173931 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/go/net')
-rw-r--r--libgo/go/net/cgo_bsd.go15
-rw-r--r--libgo/go/net/cgo_linux.go15
-rw-r--r--libgo/go/net/cgo_stub.go4
-rw-r--r--libgo/go/net/cgo_unix.go149
-rw-r--r--libgo/go/net/dial.go8
-rw-r--r--libgo/go/net/dialgoogle_test.go109
-rw-r--r--libgo/go/net/dnsclient.go91
-rw-r--r--libgo/go/net/dnsmsg.go156
-rw-r--r--libgo/go/net/dnsmsg_test.go107
-rw-r--r--libgo/go/net/hosts_test.go15
-rw-r--r--libgo/go/net/ip.go5
-rw-r--r--libgo/go/net/ip_test.go1
-rw-r--r--libgo/go/net/ipraw_test.go10
-rw-r--r--libgo/go/net/iprawsock.go2
-rw-r--r--libgo/go/net/ipsock.go46
-rw-r--r--libgo/go/net/lookup.go12
-rw-r--r--libgo/go/net/multicast_test.go11
-rw-r--r--libgo/go/net/net.go5
-rw-r--r--libgo/go/net/resolv_windows.go6
-rw-r--r--libgo/go/net/server_test.go8
-rw-r--r--libgo/go/net/sock.go14
-rw-r--r--libgo/go/net/sock_bsd.go31
-rw-r--r--libgo/go/net/sock_linux.go25
-rw-r--r--libgo/go/net/sock_windows.go25
-rw-r--r--libgo/go/net/srv_test.go7
-rw-r--r--libgo/go/net/tcpsock.go4
-rw-r--r--libgo/go/net/textproto/textproto.go5
-rw-r--r--libgo/go/net/udpsock.go4
28 files changed, 709 insertions, 181 deletions
diff --git a/libgo/go/net/cgo_bsd.go b/libgo/go/net/cgo_bsd.go
new file mode 100644
index 00000000000..d9fef45de0a
--- /dev/null
+++ b/libgo/go/net/cgo_bsd.go
@@ -0,0 +1,15 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <netdb.h>
+*/
+
+import "syscall"
+
+func cgoAddrInfoMask() C.int {
+ return syscall.AI_MASK
+}
diff --git a/libgo/go/net/cgo_linux.go b/libgo/go/net/cgo_linux.go
new file mode 100644
index 00000000000..482435221e0
--- /dev/null
+++ b/libgo/go/net/cgo_linux.go
@@ -0,0 +1,15 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <netdb.h>
+*/
+
+import "syscall"
+
+func cgoAddrInfoMask() int {
+ return syscall.AI_CANONNAME | syscall.AI_V4MAPPED | syscall.AI_ALL
+}
diff --git a/libgo/go/net/cgo_stub.go b/libgo/go/net/cgo_stub.go
index e28f6622e93..c6277cb657c 100644
--- a/libgo/go/net/cgo_stub.go
+++ b/libgo/go/net/cgo_stub.go
@@ -19,3 +19,7 @@ func cgoLookupPort(network, service string) (port int, err os.Error, completed b
func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
return nil, nil, false
}
+
+func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+ return "", nil, false
+}
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
new file mode 100644
index 00000000000..b8090181293
--- /dev/null
+++ b/libgo/go/net/cgo_unix.go
@@ -0,0 +1,149 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+/*
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+*/
+
+import (
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **syscall.Addrinfo) int __asm__ ("getaddrinfo")
+func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
+func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
+
+func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
+ ip, err, completed := cgoLookupIP(name)
+ for _, p := range ip {
+ addrs = append(addrs, p.String())
+ }
+ return
+}
+
+func cgoLookupPort(net, service string) (port int, err os.Error, completed bool) {
+ var res *syscall.Addrinfo
+ var hints syscall.Addrinfo
+
+ switch net {
+ case "":
+ // no hints
+ case "tcp", "tcp4", "tcp6":
+ hints.Ai_socktype = syscall.SOCK_STREAM
+ hints.Ai_protocol = syscall.IPPROTO_TCP
+ case "udp", "udp4", "udp6":
+ hints.Ai_socktype = syscall.SOCK_DGRAM
+ hints.Ai_protocol = syscall.IPPROTO_UDP
+ default:
+ return 0, UnknownNetworkError(net), true
+ }
+ if len(net) >= 4 {
+ switch net[3] {
+ case '4':
+ hints.Ai_family = syscall.AF_INET
+ case '6':
+ hints.Ai_family = syscall.AF_INET6
+ }
+ }
+
+ s := syscall.StringBytePtr(service)
+ if libc_getaddrinfo(nil, s, &hints, &res) == 0 {
+ defer libc_freeaddrinfo(res)
+ for r := res; r != nil; r = r.Ai_next {
+ switch r.Ai_family {
+ default:
+ continue
+ case syscall.AF_INET:
+ sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
+ p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+ return int(p[0])<<8 | int(p[1]), nil, true
+ case syscall.AF_INET6:
+ sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
+ p := (*[2]byte)(unsafe.Pointer(&sa.Port))
+ return int(p[0])<<8 | int(p[1]), nil, true
+ }
+ }
+ }
+ return 0, &AddrError{"unknown port", net + "/" + service}, true
+}
+
+func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, completed bool) {
+ var res *syscall.Addrinfo
+ var hints syscall.Addrinfo
+
+ // NOTE(rsc): In theory there are approximately balanced
+ // arguments for and against including AI_ADDRCONFIG
+ // in the flags (it includes IPv4 results only on IPv4 systems,
+ // and similarly for IPv6), but in practice setting it causes
+ // getaddrinfo to return the wrong canonical name on Linux.
+ // So definitely leave it out.
+ hints.Ai_flags = int32((syscall.AI_ALL | syscall.AI_V4MAPPED | syscall.AI_CANONNAME) & cgoAddrInfoMask())
+
+ h := syscall.StringBytePtr(name)
+ gerrno := libc_getaddrinfo(h, nil, &hints, &res)
+ if gerrno != 0 {
+ var str string
+ if gerrno == syscall.EAI_NONAME {
+ str = noSuchHost
+ } else if gerrno == syscall.EAI_SYSTEM {
+ str = syscall.Errstr(syscall.GetErrno())
+ } else {
+ str = syscall.BytePtrToString(libc_gai_strerror(gerrno))
+ }
+ return nil, "", &DNSError{Error: str, Name: name}, true
+ }
+ defer libc_freeaddrinfo(res)
+ if res != nil {
+ cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
+ if cname == "" {
+ cname = name
+ }
+ if len(cname) > 0 && cname[len(cname)-1] != '.' {
+ cname += "."
+ }
+ }
+ for r := res; r != nil; r = r.Ai_next {
+ // Everything comes back twice, once for UDP and once for TCP.
+ if r.Ai_socktype != syscall.SOCK_STREAM {
+ continue
+ }
+ switch r.Ai_family {
+ default:
+ continue
+ case syscall.AF_INET:
+ sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.Ai_addr))
+ addrs = append(addrs, copyIP(sa.Addr[:]))
+ case syscall.AF_INET6:
+ sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.Ai_addr))
+ addrs = append(addrs, copyIP(sa.Addr[:]))
+ }
+ }
+ return addrs, cname, nil, true
+}
+
+func cgoLookupIP(name string) (addrs []IP, err os.Error, completed bool) {
+ addrs, _, err, completed = cgoLookupIPCNAME(name)
+ return
+}
+
+func cgoLookupCNAME(name string) (cname string, err os.Error, completed bool) {
+ _, cname, err, completed = cgoLookupIPCNAME(name)
+ return
+}
+
+func copyIP(x IP) IP {
+ y := make(IP, len(x))
+ copy(y, x)
+ return y
+}
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 66cb09b19bb..16896b4269b 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -30,7 +30,7 @@ func Dial(net, addr string) (c Conn, err os.Error) {
switch net {
case "tcp", "tcp4", "tcp6":
var ra *TCPAddr
- if ra, err = ResolveTCPAddr(raddr); err != nil {
+ if ra, err = ResolveTCPAddr(net, raddr); err != nil {
goto Error
}
c, err := DialTCP(net, nil, ra)
@@ -40,7 +40,7 @@ func Dial(net, addr string) (c Conn, err os.Error) {
return c, nil
case "udp", "udp4", "udp6":
var ra *UDPAddr
- if ra, err = ResolveUDPAddr(raddr); err != nil {
+ if ra, err = ResolveUDPAddr(net, raddr); err != nil {
goto Error
}
c, err := DialUDP(net, nil, ra)
@@ -83,7 +83,7 @@ func Listen(net, laddr string) (l Listener, err os.Error) {
case "tcp", "tcp4", "tcp6":
var la *TCPAddr
if laddr != "" {
- if la, err = ResolveTCPAddr(laddr); err != nil {
+ if la, err = ResolveTCPAddr(net, laddr); err != nil {
return nil, err
}
}
@@ -116,7 +116,7 @@ func ListenPacket(net, laddr string) (c PacketConn, err os.Error) {
case "udp", "udp4", "udp6":
var la *UDPAddr
if laddr != "" {
- if la, err = ResolveUDPAddr(laddr); err != nil {
+ if la, err = ResolveUDPAddr(net, laddr); err != nil {
return nil, err
}
}
diff --git a/libgo/go/net/dialgoogle_test.go b/libgo/go/net/dialgoogle_test.go
index 9a9c02ebd71..e90c4f3f894 100644
--- a/libgo/go/net/dialgoogle_test.go
+++ b/libgo/go/net/dialgoogle_test.go
@@ -41,7 +41,19 @@ func doDial(t *testing.T, network, addr string) {
fd.Close()
}
-var googleaddrs = []string{
+func TestLookupCNAME(t *testing.T) {
+ if testing.Short() {
+ // Don't use external network.
+ t.Logf("skipping external network test during -short")
+ return
+ }
+ cname, err := LookupCNAME("www.google.com")
+ if !strings.HasSuffix(cname, ".l.google.com.") || err != nil {
+ t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "*.l.google.com.", nil`, cname, err)
+ }
+}
+
+var googleaddrsipv4 = []string{
"%d.%d.%d.%d:80",
"www.google.com:80",
"%d.%d.%d.%d:http",
@@ -52,42 +64,40 @@ var googleaddrs = []string{
"[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
"[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
"[0:0:0:0:0:ffff::%d.%d.%d.%d]:80",
- "[2001:4860:0:2001::68]:80", // ipv6.google.com; removed if ipv6 flag not set
}
-func TestLookupCNAME(t *testing.T) {
- cname, err := LookupCNAME("www.google.com")
- if cname != "www.l.google.com." || err != nil {
- t.Errorf(`LookupCNAME("www.google.com.") = %q, %v, want "www.l.google.com.", nil`, cname, err)
- }
-}
-
-func TestDialGoogle(t *testing.T) {
- // If no ipv6 tunnel, don't try the last address.
- if !*ipv6 {
- googleaddrs[len(googleaddrs)-1] = ""
+func TestDialGoogleIPv4(t *testing.T) {
+ if testing.Short() {
+ // Don't use external network.
+ t.Logf("skipping external network test during -short")
+ return
}
- // Insert an actual IP address for google.com
+ // Insert an actual IPv4 address for google.com
// into the table.
-
addrs, err := LookupIP("www.google.com")
if err != nil {
t.Fatalf("lookup www.google.com: %v", err)
}
- if len(addrs) == 0 {
- t.Fatalf("no addresses for www.google.com")
+ var ip IP
+ for _, addr := range addrs {
+ if x := addr.To4(); x != nil {
+ ip = x
+ break
+ }
+ }
+ if ip == nil {
+ t.Fatalf("no IPv4 addresses for www.google.com")
}
- ip := addrs[0].To4()
- for i, s := range googleaddrs {
+ for i, s := range googleaddrsipv4 {
if strings.Contains(s, "%") {
- googleaddrs[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3])
+ googleaddrsipv4[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3])
}
}
- for i := 0; i < len(googleaddrs); i++ {
- addr := googleaddrs[i]
+ for i := 0; i < len(googleaddrsipv4); i++ {
+ addr := googleaddrsipv4[i]
if addr == "" {
continue
}
@@ -95,20 +105,67 @@ func TestDialGoogle(t *testing.T) {
doDial(t, "tcp", addr)
if addr[0] != '[' {
doDial(t, "tcp4", addr)
-
if !preferIPv4 {
// make sure preferIPv4 flag works.
preferIPv4 = true
syscall.SocketDisableIPv6 = true
+ doDial(t, "tcp", addr)
doDial(t, "tcp4", addr)
syscall.SocketDisableIPv6 = false
preferIPv4 = false
}
}
+ }
+}
+
+var googleaddrsipv6 = []string{
+ "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
+ "ipv6.google.com:80",
+ "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
+ "ipv6.google.com:http",
+}
- // Only run tcp6 if the kernel will take it.
- if kernelSupportsIPv6() {
- doDial(t, "tcp6", addr)
+func TestDialGoogleIPv6(t *testing.T) {
+ if testing.Short() {
+ // Don't use external network.
+ t.Logf("skipping external network test during -short")
+ return
+ }
+ // Only run tcp6 if the kernel will take it.
+ if !*ipv6 || !kernelSupportsIPv6() {
+ return
+ }
+
+ // Insert an actual IPv6 address for ipv6.google.com
+ // into the table.
+ addrs, err := LookupIP("ipv6.google.com")
+ if err != nil {
+ t.Fatalf("lookup ipv6.google.com: %v", err)
+ }
+ var ip IP
+ for _, addr := range addrs {
+ if x := addr.To16(); x != nil {
+ ip = x
+ break
+ }
+ }
+ if ip == nil {
+ t.Fatalf("no IPv6 addresses for ipv6.google.com")
+ }
+
+ for i, s := range googleaddrsipv6 {
+ if strings.Contains(s, "%") {
+ googleaddrsipv6[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15])
+ }
+ }
+
+ for i := 0; i < len(googleaddrsipv6); i++ {
+ addr := googleaddrsipv6[i]
+ if addr == "" {
+ continue
}
+ t.Logf("-- %s --", addr)
+ doDial(t, "tcp", addr)
+ doDial(t, "tcp6", addr)
}
}
diff --git a/libgo/go/net/dnsclient.go b/libgo/go/net/dnsclient.go
index 32cea6125eb..3466003fab8 100644
--- a/libgo/go/net/dnsclient.go
+++ b/libgo/go/net/dnsclient.go
@@ -21,6 +21,7 @@ import (
"rand"
"sync"
"time"
+ "sort"
)
// DNSError represents a DNS lookup error.
@@ -120,15 +121,19 @@ func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs
Cname:
for cnameloop := 0; cnameloop < 10; cnameloop++ {
addrs = addrs[0:0]
- for i := 0; i < len(dns.answer); i++ {
- rr := dns.answer[i]
+ for _, rr := range dns.answer {
+ if _, justHeader := rr.(*dnsRR_Header); justHeader {
+ // Corrupt record: we only have a
+ // header. That header might say it's
+ // of type qtype, but we don't
+ // actually have it. Skip.
+ continue
+ }
h := rr.Header()
if h.Class == dnsClassINET && h.Name == name {
switch h.Rrtype {
case qtype:
- n := len(addrs)
- addrs = addrs[0 : n+1]
- addrs[n] = rr
+ addrs = append(addrs, rr)
case dnsTypeCNAME:
// redirect to cname
name = rr.(*dnsRR_CNAME).Cname
@@ -180,8 +185,7 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (cname string, addrs
func convertRR_A(records []dnsRR) []IP {
addrs := make([]IP, len(records))
- for i := 0; i < len(records); i++ {
- rr := records[i]
+ for i, rr := range records {
a := rr.(*dnsRR_A).A
addrs[i] = IPv4(byte(a>>24), byte(a>>16), byte(a>>8), byte(a))
}
@@ -190,8 +194,7 @@ func convertRR_A(records []dnsRR) []IP {
func convertRR_AAAA(records []dnsRR) []IP {
addrs := make([]IP, len(records))
- for i := 0; i < len(records); i++ {
- rr := records[i]
+ for i, rr := range records {
a := make(IP, 16)
copy(a, rr.(*dnsRR_AAAA).AAAA[:])
addrs[i] = a
@@ -306,17 +309,22 @@ func lookup(name string, qtype uint16) (cname string, addrs []dnsRR, err os.Erro
}
// goLookupHost is the native Go implementation of LookupHost.
+// Used only if cgoLookupHost refuses to handle the request
+// (that is, only if cgoLookupHost is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
func goLookupHost(name string) (addrs []string, err os.Error) {
- onceLoadConfig.Do(loadConfig)
- if dnserr != nil || cfg == nil {
- err = dnserr
- return
- }
// Use entries from /etc/hosts if they match.
addrs = lookupStaticHost(name)
if len(addrs) > 0 {
return
}
+ onceLoadConfig.Do(loadConfig)
+ if dnserr != nil || cfg == nil {
+ err = dnserr
+ return
+ }
ips, err := goLookupIP(name)
if err != nil {
return
@@ -329,6 +337,11 @@ func goLookupHost(name string) (addrs []string, err os.Error) {
}
// goLookupIP is the native Go implementation of LookupIP.
+// Used only if cgoLookupIP refuses to handle the request
+// (that is, only if cgoLookupIP is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
func goLookupIP(name string) (addrs []IP, err os.Error) {
onceLoadConfig.Do(loadConfig)
if dnserr != nil || cfg == nil {
@@ -357,11 +370,13 @@ func goLookupIP(name string) (addrs []IP, err os.Error) {
return
}
-// LookupCNAME returns the canonical DNS host for the given name.
-// Callers that do not care about the canonical name can call
-// LookupHost or LookupIP directly; both take care of resolving
-// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err os.Error) {
+// goLookupCNAME is the native Go implementation of LookupCNAME.
+// Used only if cgoLookupCNAME refuses to handle the request
+// (that is, only if cgoLookupCNAME is the stub in cgo_stub.go).
+// Normally we let cgo use the C library resolver instead of
+// depending on our lookup code, so that Go and C get the same
+// answers.
+func goLookupCNAME(name string) (cname string, err os.Error) {
onceLoadConfig.Do(loadConfig)
if dnserr != nil || cfg == nil {
err = dnserr
@@ -371,9 +386,7 @@ func LookupCNAME(name string) (cname string, err os.Error) {
if err != nil {
return
}
- if len(rr) >= 0 {
- cname = rr[0].(*dnsRR_CNAME).Cname
- }
+ cname = rr[0].(*dnsRR_CNAME).Cname
return
}
@@ -397,8 +410,8 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
return
}
addrs = make([]*SRV, len(records))
- for i := 0; i < len(records); i++ {
- r := records[i].(*dnsRR_SRV)
+ for i, rr := range records {
+ r := rr.(*dnsRR_SRV)
addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
}
return
@@ -410,18 +423,32 @@ type MX struct {
Pref uint16
}
-// LookupMX returns the DNS MX records associated with name.
-func LookupMX(name string) (entries []*MX, err os.Error) {
- var records []dnsRR
- _, records, err = lookup(name, dnsTypeMX)
+// byPref implements sort.Interface to sort MX records by preference
+type byPref []*MX
+
+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] }
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) (mx []*MX, err os.Error) {
+ _, rr, err := lookup(name, dnsTypeMX)
if err != nil {
return
}
- entries = make([]*MX, len(records))
- for i := range records {
- r := records[i].(*dnsRR_MX)
- entries[i] = &MX{r.Mx, r.Pref}
+ mx = make([]*MX, len(rr))
+ for i := range rr {
+ 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))
return
}
diff --git a/libgo/go/net/dnsmsg.go b/libgo/go/net/dnsmsg.go
index 5209c1a06a5..731efe26a44 100644
--- a/libgo/go/net/dnsmsg.go
+++ b/libgo/go/net/dnsmsg.go
@@ -390,52 +390,48 @@ Loop:
// TODO(rsc): Move into generic library?
// Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string,
// [n]byte, and other (often anonymous) structs.
-func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
+func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) {
for i := 0; i < val.NumField(); i++ {
- f := val.Type().(*reflect.StructType).Field(i)
- switch fv := val.Field(i).(type) {
+ f := val.Type().Field(i)
+ switch fv := val.Field(i); fv.Kind() {
default:
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
return len(msg), false
- case *reflect.StructValue:
+ case reflect.Struct:
off, ok = packStructValue(fv, msg, off)
- case *reflect.UintValue:
- i := fv.Get()
- switch fv.Type().Kind() {
- default:
- goto BadType
- case reflect.Uint16:
- if off+2 > len(msg) {
- return len(msg), false
- }
- msg[off] = byte(i >> 8)
- msg[off+1] = byte(i)
- off += 2
- case reflect.Uint32:
- if off+4 > len(msg) {
- return len(msg), false
- }
- msg[off] = byte(i >> 24)
- msg[off+1] = byte(i >> 16)
- msg[off+2] = byte(i >> 8)
- msg[off+3] = byte(i)
- off += 4
+ case reflect.Uint16:
+ if off+2 > len(msg) {
+ return len(msg), false
}
- case *reflect.ArrayValue:
- if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 {
+ i := fv.Uint()
+ msg[off] = byte(i >> 8)
+ msg[off+1] = byte(i)
+ off += 2
+ case reflect.Uint32:
+ if off+4 > len(msg) {
+ return len(msg), false
+ }
+ i := fv.Uint()
+ msg[off] = byte(i >> 24)
+ msg[off+1] = byte(i >> 16)
+ msg[off+2] = byte(i >> 8)
+ msg[off+3] = byte(i)
+ off += 4
+ case reflect.Array:
+ if fv.Type().Elem().Kind() != reflect.Uint8 {
goto BadType
}
n := fv.Len()
if off+n > len(msg) {
return len(msg), false
}
- reflect.Copy(reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue), fv)
+ reflect.Copy(reflect.ValueOf(msg[off:off+n]), fv)
off += n
- case *reflect.StringValue:
+ case reflect.String:
// There are multiple string encodings.
// The tag distinguishes ordinary strings from domain names.
- s := fv.Get()
+ s := fv.String()
switch f.Tag {
default:
fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag)
@@ -459,8 +455,8 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
return off, true
}
-func structValue(any interface{}) *reflect.StructValue {
- return reflect.NewValue(any).(*reflect.PtrValue).Elem().(*reflect.StructValue)
+func structValue(any interface{}) reflect.Value {
+ return reflect.ValueOf(any).Elem()
}
func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
@@ -471,46 +467,41 @@ func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
// TODO(rsc): Move into generic library?
// Unpack a reflect.StructValue from msg.
// Same restrictions as packStructValue.
-func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
+func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) {
for i := 0; i < val.NumField(); i++ {
- f := val.Type().(*reflect.StructType).Field(i)
- switch fv := val.Field(i).(type) {
+ f := val.Type().Field(i)
+ switch fv := val.Field(i); fv.Kind() {
default:
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
return len(msg), false
- case *reflect.StructValue:
+ case reflect.Struct:
off, ok = unpackStructValue(fv, msg, off)
- case *reflect.UintValue:
- switch fv.Type().Kind() {
- default:
- goto BadType
- case reflect.Uint16:
- if off+2 > len(msg) {
- return len(msg), false
- }
- i := uint16(msg[off])<<8 | uint16(msg[off+1])
- fv.Set(uint64(i))
- off += 2
- case reflect.Uint32:
- if off+4 > len(msg) {
- return len(msg), false
- }
- i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
- fv.Set(uint64(i))
- off += 4
+ case reflect.Uint16:
+ if off+2 > len(msg) {
+ return len(msg), false
}
- case *reflect.ArrayValue:
- if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 {
+ i := uint16(msg[off])<<8 | uint16(msg[off+1])
+ fv.SetUint(uint64(i))
+ off += 2
+ case reflect.Uint32:
+ if off+4 > len(msg) {
+ return len(msg), false
+ }
+ i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
+ fv.SetUint(uint64(i))
+ off += 4
+ case reflect.Array:
+ if fv.Type().Elem().Kind() != reflect.Uint8 {
goto BadType
}
n := fv.Len()
if off+n > len(msg) {
return len(msg), false
}
- reflect.Copy(fv, reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue))
+ reflect.Copy(fv, reflect.ValueOf(msg[off:off+n]))
off += n
- case *reflect.StringValue:
+ case reflect.String:
var s string
switch f.Tag {
default:
@@ -534,7 +525,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
off += n
s = string(b)
}
- fv.Set(s)
+ fv.SetString(s)
}
}
return off, true
@@ -550,23 +541,23 @@ func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
// but does look for an "ipv4" tag on uint32 variables
// and the "ipv6" tag on array variables,
// printing them as IP addresses.
-func printStructValue(val *reflect.StructValue) string {
+func printStructValue(val reflect.Value) string {
s := "{"
for i := 0; i < val.NumField(); i++ {
if i > 0 {
s += ", "
}
- f := val.Type().(*reflect.StructType).Field(i)
+ f := val.Type().Field(i)
if !f.Anonymous {
s += f.Name + "="
}
fval := val.Field(i)
- if fv, ok := fval.(*reflect.StructValue); ok {
+ if fv := fval; fv.Kind() == reflect.Struct {
s += printStructValue(fv)
- } else if fv, ok := fval.(*reflect.UintValue); ok && f.Tag == "ipv4" {
- i := fv.Get()
+ } else if fv := fval; (fv.Kind() == reflect.Uint || fv.Kind() == reflect.Uint8 || fv.Kind() == reflect.Uint16 || fv.Kind() == reflect.Uint32 || fv.Kind() == reflect.Uint64 || fv.Kind() == reflect.Uintptr) && f.Tag == "ipv4" {
+ i := fv.Uint()
s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
- } else if fv, ok := fval.(*reflect.ArrayValue); ok && f.Tag == "ipv6" {
+ } else if fv := fval; fv.Kind() == reflect.Array && f.Tag == "ipv6" {
i := fv.Interface().([]byte)
s += IP(i).String()
} else {
@@ -724,24 +715,35 @@ func (dns *dnsMsg) Unpack(msg []byte) bool {
// Arrays.
dns.question = make([]dnsQuestion, dh.Qdcount)
- dns.answer = make([]dnsRR, dh.Ancount)
- dns.ns = make([]dnsRR, dh.Nscount)
- dns.extra = make([]dnsRR, dh.Arcount)
+ dns.answer = make([]dnsRR, 0, dh.Ancount)
+ dns.ns = make([]dnsRR, 0, dh.Nscount)
+ dns.extra = make([]dnsRR, 0, dh.Arcount)
+
+ var rec dnsRR
for i := 0; i < len(dns.question); i++ {
off, ok = unpackStruct(&dns.question[i], msg, off)
}
- for i := 0; i < len(dns.answer); i++ {
- dns.answer[i], off, ok = unpackRR(msg, off)
- }
- for i := 0; i < len(dns.ns); i++ {
- dns.ns[i], off, ok = unpackRR(msg, off)
+ for i := 0; i < int(dh.Ancount); i++ {
+ rec, off, ok = unpackRR(msg, off)
+ if !ok {
+ return false
+ }
+ dns.answer = append(dns.answer, rec)
}
- for i := 0; i < len(dns.extra); i++ {
- dns.extra[i], off, ok = unpackRR(msg, off)
+ for i := 0; i < int(dh.Nscount); i++ {
+ rec, off, ok = unpackRR(msg, off)
+ if !ok {
+ return false
+ }
+ dns.ns = append(dns.ns, rec)
}
- if !ok {
- return false
+ for i := 0; i < int(dh.Arcount); i++ {
+ rec, off, ok = unpackRR(msg, off)
+ if !ok {
+ return false
+ }
+ dns.extra = append(dns.extra, rec)
}
// if off != len(msg) {
// println("extra bytes in dns packet", off, "<", len(msg));
diff --git a/libgo/go/net/dnsmsg_test.go b/libgo/go/net/dnsmsg_test.go
new file mode 100644
index 00000000000..20c9f02b0b4
--- /dev/null
+++ b/libgo/go/net/dnsmsg_test.go
@@ -0,0 +1,107 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "encoding/hex"
+ "runtime"
+ "testing"
+)
+
+func TestDNSParseSRVReply(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+ data, err := hex.DecodeString(dnsSRVReply)
+ if err != nil {
+ t.Fatal(err)
+ }
+ msg := new(dnsMsg)
+ ok := msg.Unpack(data)
+ if !ok {
+ t.Fatalf("unpacking packet failed")
+ }
+ if g, e := len(msg.answer), 5; g != e {
+ t.Errorf("len(msg.answer) = %d; want %d", g, e)
+ }
+ for idx, rr := range msg.answer {
+ if g, e := rr.Header().Rrtype, uint16(dnsTypeSRV); g != e {
+ t.Errorf("rr[%d].Header().Rrtype = %d; want %d", idx, g, e)
+ }
+ if _, ok := rr.(*dnsRR_SRV); !ok {
+ t.Errorf("answer[%d] = %T; want *dnsRR_SRV", idx, rr)
+ }
+ }
+ _, addrs, err := answer("_xmpp-server._tcp.google.com.", "foo:53", msg, uint16(dnsTypeSRV))
+ if err != nil {
+ t.Fatalf("answer: %v", err)
+ }
+ if g, e := len(addrs), 5; g != e {
+ t.Errorf("len(addrs) = %d; want %d", g, e)
+ t.Logf("addrs = %#v", addrs)
+ }
+}
+
+func TestDNSParseCorruptSRVReply(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+ data, err := hex.DecodeString(dnsSRVCorruptReply)
+ if err != nil {
+ t.Fatal(err)
+ }
+ msg := new(dnsMsg)
+ ok := msg.Unpack(data)
+ if !ok {
+ t.Fatalf("unpacking packet failed")
+ }
+ if g, e := len(msg.answer), 5; g != e {
+ t.Errorf("len(msg.answer) = %d; want %d", g, e)
+ }
+ for idx, rr := range msg.answer {
+ if g, e := rr.Header().Rrtype, uint16(dnsTypeSRV); g != e {
+ t.Errorf("rr[%d].Header().Rrtype = %d; want %d", idx, g, e)
+ }
+ if idx == 4 {
+ if _, ok := rr.(*dnsRR_Header); !ok {
+ t.Errorf("answer[%d] = %T; want *dnsRR_Header", idx, rr)
+ }
+ } else {
+ if _, ok := rr.(*dnsRR_SRV); !ok {
+ t.Errorf("answer[%d] = %T; want *dnsRR_SRV", idx, rr)
+ }
+ }
+ }
+ _, addrs, err := answer("_xmpp-server._tcp.google.com.", "foo:53", msg, uint16(dnsTypeSRV))
+ if err != nil {
+ t.Fatalf("answer: %v", err)
+ }
+ if g, e := len(addrs), 4; g != e {
+ t.Errorf("len(addrs) = %d; want %d", g, e)
+ t.Logf("addrs = %#v", addrs)
+ }
+}
+
+// Valid DNS SRV reply
+const dnsSRVReply = "0901818000010005000000000c5f786d70702d736572766572045f74637006676f6f67" +
+ "6c6503636f6d0000210001c00c002100010000012c00210014000014950c786d70702d" +
+ "73657276657234016c06676f6f676c6503636f6d00c00c002100010000012c00210014" +
+ "000014950c786d70702d73657276657232016c06676f6f676c6503636f6d00c00c0021" +
+ "00010000012c00210014000014950c786d70702d73657276657233016c06676f6f676c" +
+ "6503636f6d00c00c002100010000012c00200005000014950b786d70702d7365727665" +
+ "72016c06676f6f676c6503636f6d00c00c002100010000012c00210014000014950c78" +
+ "6d70702d73657276657231016c06676f6f676c6503636f6d00"
+
+// Corrupt DNS SRV reply, with its final RR having a bogus length
+// (perhaps it was truncated, or it's malicious) The mutation is the
+// capital "FF" below, instead of the proper "21".
+const dnsSRVCorruptReply = "0901818000010005000000000c5f786d70702d736572766572045f74637006676f6f67" +
+ "6c6503636f6d0000210001c00c002100010000012c00210014000014950c786d70702d" +
+ "73657276657234016c06676f6f676c6503636f6d00c00c002100010000012c00210014" +
+ "000014950c786d70702d73657276657232016c06676f6f676c6503636f6d00c00c0021" +
+ "00010000012c00210014000014950c786d70702d73657276657233016c06676f6f676c" +
+ "6503636f6d00c00c002100010000012c00200005000014950b786d70702d7365727665" +
+ "72016c06676f6f676c6503636f6d00c00c002100010000012c00FF0014000014950c78" +
+ "6d70702d73657276657231016c06676f6f676c6503636f6d00"
diff --git a/libgo/go/net/hosts_test.go b/libgo/go/net/hosts_test.go
index 470e35f7863..e5793eef2c7 100644
--- a/libgo/go/net/hosts_test.go
+++ b/libgo/go/net/hosts_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "sort"
"testing"
)
@@ -51,3 +52,17 @@ func TestLookupStaticHost(t *testing.T) {
}
hostsPath = p
}
+
+func TestLookupHost(t *testing.T) {
+ // Can't depend on this to return anything in particular,
+ // but if it does return something, make sure it doesn't
+ // duplicate addresses (a common bug due to the way
+ // getaddrinfo works).
+ addrs, _ := LookupHost("localhost")
+ sort.SortStrings(addrs)
+ for i := 0; i+1 < len(addrs); i++ {
+ if addrs[i] == addrs[i+1] {
+ t.Fatalf("LookupHost(\"localhost\") = %v, has duplicate addresses", addrs)
+ }
+ }
+}
diff --git a/libgo/go/net/ip.go b/libgo/go/net/ip.go
index 12bb6f351a1..61b2c687e2f 100644
--- a/libgo/go/net/ip.go
+++ b/libgo/go/net/ip.go
@@ -75,7 +75,8 @@ var (
// Well-known IPv6 addresses
var (
- IPzero = make(IP, IPv6len) // all zeros
+ IPzero = make(IP, IPv6len) // all zeros
+ IPv6loopback = IP([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})
)
// Is p all zeros?
@@ -436,7 +437,7 @@ func parseIPv6(s string) IP {
}
// Otherwise must be followed by colon and more.
- if s[i] != ':' && i+1 == len(s) {
+ if s[i] != ':' || i+1 == len(s) {
return nil
}
i++
diff --git a/libgo/go/net/ip_test.go b/libgo/go/net/ip_test.go
index f1a4716d227..2008953ef38 100644
--- a/libgo/go/net/ip_test.go
+++ b/libgo/go/net/ip_test.go
@@ -29,6 +29,7 @@ var parseiptests = []struct {
{"127.0.0.1", IPv4(127, 0, 0, 1)},
{"127.0.0.256", nil},
{"abc", nil},
+ {"123:", nil},
{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
{"2001:4860:0:2001::68",
IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01,
diff --git a/libgo/go/net/ipraw_test.go b/libgo/go/net/ipraw_test.go
index 562298bdf46..0c0b675f875 100644
--- a/libgo/go/net/ipraw_test.go
+++ b/libgo/go/net/ipraw_test.go
@@ -60,7 +60,8 @@ func parsePingReply(p []byte) (id, seq int) {
}
var srchost = flag.String("srchost", "", "Source of the ICMP ECHO request")
-var dsthost = flag.String("dsthost", "localhost", "Destination for the ICMP ECHO request")
+// 127.0.0.1 because this is an IPv4-specific test.
+var dsthost = flag.String("dsthost", "127.0.0.1", "Destination for the ICMP ECHO request")
// test (raw) IP socket using ICMP
func TestICMP(t *testing.T) {
@@ -69,9 +70,12 @@ func TestICMP(t *testing.T) {
return
}
- var laddr *IPAddr
+ var (
+ laddr *IPAddr
+ err os.Error
+ )
if *srchost != "" {
- laddr, err := ResolveIPAddr(*srchost)
+ laddr, err = ResolveIPAddr(*srchost)
if err != nil {
t.Fatalf(`net.ResolveIPAddr("%v") = %v, %v`, *srchost, laddr, err)
}
diff --git a/libgo/go/net/iprawsock.go b/libgo/go/net/iprawsock.go
index 60433303ae1..5be6fe4e0b9 100644
--- a/libgo/go/net/iprawsock.go
+++ b/libgo/go/net/iprawsock.go
@@ -245,7 +245,7 @@ func hostToIP(host string) (ip IP, err os.Error) {
err = err1
goto Error
}
- addr = firstSupportedAddr(addrs)
+ addr = firstSupportedAddr(anyaddr, addrs)
if addr == nil {
// should not happen
err = &AddrError{"LookupHost returned invalid address", addrs[0]}
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index 80bc3eea5da..e8bcac64603 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -35,15 +35,28 @@ func kernelSupportsIPv6() bool {
var preferIPv4 = !kernelSupportsIPv6()
-func firstSupportedAddr(addrs []string) (addr IP) {
+func firstSupportedAddr(filter func(IP) IP, addrs []string) IP {
for _, s := range addrs {
- addr = ParseIP(s)
- if !preferIPv4 || addr.To4() != nil {
- break
+ if addr := filter(ParseIP(s)); addr != nil {
+ return addr
}
- addr = nil
}
- return addr
+ return nil
+}
+
+func anyaddr(x IP) IP { return x }
+func ipv4only(x IP) IP { return x.To4() }
+
+func ipv6only(x IP) IP {
+ // Only return addresses that we can use
+ // with the kernel's IPv6 addressing modes.
+ // If preferIPv4 is set, it means the IPv6 stack
+ // cannot take IPv4 addresses directly (we prefer
+ // to use the IPv4 stack) so reject IPv4 addresses.
+ if x.To4() != nil && preferIPv4 {
+ return nil
+ }
+ return x
}
// TODO(rsc): if syscall.OS == "linux", we're supposd to read
@@ -131,7 +144,6 @@ func (e InvalidAddrError) String() string { return string(e) }
func (e InvalidAddrError) Timeout() bool { return false }
func (e InvalidAddrError) Temporary() bool { return false }
-
func ipToSockaddr(family int, ip IP, port int) (syscall.Sockaddr, os.Error) {
switch family {
case syscall.AF_INET:
@@ -218,13 +230,31 @@ func hostPortToIP(net, hostport string) (ip IP, iport int, err os.Error) {
// Try as an IP address.
addr = ParseIP(host)
if addr == nil {
+ filter := anyaddr
+ if len(net) >= 4 && net[3] == '4' {
+ filter = ipv4only
+ } else if len(net) >= 4 && net[3] == '6' {
+ filter = ipv6only
+ }
// Not an IP address. Try as a DNS name.
addrs, err1 := LookupHost(host)
if err1 != nil {
err = err1
goto Error
}
- addr = firstSupportedAddr(addrs)
+ if filter == anyaddr {
+ // We'll take any IP address, but since the dialing code
+ // does not yet try multiple addresses, prefer to use
+ // an IPv4 address if possible. This is especially relevant
+ // if localhost resolves to [ipv6-localhost, ipv4-localhost].
+ // Too much code assumes localhost == ipv4-localhost.
+ addr = firstSupportedAddr(ipv4only, addrs)
+ if addr == nil {
+ addr = firstSupportedAddr(anyaddr, addrs)
+ }
+ } else {
+ addr = firstSupportedAddr(filter, addrs)
+ }
if addr == nil {
// should not happen
err = &AddrError{"LookupHost returned invalid address", addrs[0]}
diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go
index 7b2185ed419..eeb22a8ae3d 100644
--- a/libgo/go/net/lookup.go
+++ b/libgo/go/net/lookup.go
@@ -36,3 +36,15 @@ func LookupPort(network, service string) (port int, err os.Error) {
}
return
}
+
+// LookupCNAME returns the canonical DNS host for the given name.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+func LookupCNAME(name string) (cname string, err os.Error) {
+ cname, err, ok := cgoLookupCNAME(name)
+ if !ok {
+ cname, err = goLookupCNAME(name)
+ }
+ return
+}
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go
index 32fdec85bde..be6dbf2dc19 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_test.go
@@ -5,14 +5,21 @@
package net
import (
+ "flag"
"runtime"
"testing"
)
+var multicast = flag.Bool("multicast", false, "enable multicast tests")
+
func TestMulticastJoinAndLeave(t *testing.T) {
if runtime.GOOS == "windows" {
return
}
+ if !*multicast {
+ t.Logf("test disabled; use --multicast to enable")
+ return
+ }
addr := &UDPAddr{
IP: IPv4zero,
@@ -40,6 +47,10 @@ func TestMulticastJoinAndLeave(t *testing.T) {
}
func TestJoinFailureWithIPv6Address(t *testing.T) {
+ if !*multicast {
+ t.Logf("test disabled; use --multicast to enable")
+ return
+ }
addr := &UDPAddr{
IP: IPv4zero,
Port: 0,
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index 04a898a9aac..51db1073954 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The net package provides a portable interface to Unix
-// networks sockets, including TCP/IP, UDP, domain name
-// resolution, and Unix domain sockets.
+// Package net provides a portable interface to Unix networks sockets,
+// including TCP/IP, UDP, domain name resolution, and Unix domain sockets.
package net
// TODO(rsc):
diff --git a/libgo/go/net/resolv_windows.go b/libgo/go/net/resolv_windows.go
index 000c3065911..f7c3f51bef1 100644
--- a/libgo/go/net/resolv_windows.go
+++ b/libgo/go/net/resolv_windows.go
@@ -47,7 +47,7 @@ func goLookupIP(name string) (addrs []IP, err os.Error) {
return addrs, nil
}
-func LookupCNAME(name string) (cname string, err os.Error) {
+func goLookupCNAME(name string) (cname string, err os.Error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
if int(e) != 0 {
@@ -113,6 +113,10 @@ func reverseaddr(addr string) (arpa string, err os.Error) {
panic("unimplemented")
}
+func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err os.Error) {
+ panic("unimplemented")
+}
+
// DNSError represents a DNS lookup error.
type DNSError struct {
Error string // description of the error
diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go
index 37695a068d1..075748b83b0 100644
--- a/libgo/go/net/server_test.go
+++ b/libgo/go/net/server_test.go
@@ -108,12 +108,10 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
}
func TestTCPServer(t *testing.T) {
- doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
- doTest(t, "tcp", "", "127.0.0.1")
+ doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
if kernelSupportsIPv6() {
- doTest(t, "tcp", "[::]", "[::ffff:127.0.0.1]")
- doTest(t, "tcp", "[::]", "127.0.0.1")
- doTest(t, "tcp", "0.0.0.0", "[::ffff:127.0.0.1]")
+ doTest(t, "tcp", "[::1]", "[::1]")
+ doTest(t, "tcp", "127.0.0.1", "[::ffff:127.0.0.1]")
}
}
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index 933700af160..21bd5f03e89 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -32,17 +32,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
syscall.CloseOnExec(s)
syscall.ForkLock.RUnlock()
- // Allow reuse of recently-used addresses.
- syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
-
- // Allow broadcast.
- syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
-
- if f == syscall.AF_INET6 {
- // using ip, tcp, udp, etc.
- // allow both protocols even if the OS default is otherwise.
- syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
- }
+ setKernelSpecificSockopt(s, f)
if la != nil {
e = syscall.Bind(s, la)
@@ -161,7 +151,7 @@ type UnknownSocketError struct {
}
func (e *UnknownSocketError) String() string {
- return "unknown socket address type " + reflect.Typeof(e.sa).String()
+ return "unknown socket address type " + reflect.TypeOf(e.sa).String()
}
func sockaddrToString(sa syscall.Sockaddr) (name string, err os.Error) {
diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go
new file mode 100644
index 00000000000..5fd52074ad3
--- /dev/null
+++ b/libgo/go/net/sock_bsd.go
@@ -0,0 +1,31 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Sockets for BSD variants
+
+package net
+
+import (
+ "syscall"
+)
+
+func setKernelSpecificSockopt(s, f int) {
+ // Allow reuse of recently-used addresses.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+ // Allow reuse of recently-used ports.
+ // This option is supported only in descendants of 4.4BSD,
+ // to make an effective multicast application and an application
+ // that requires quick draw possible.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
+
+ // Allow broadcast.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+ if f == syscall.AF_INET6 {
+ // using ip, tcp, udp, etc.
+ // allow both protocols even if the OS default is otherwise.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+ }
+}
diff --git a/libgo/go/net/sock_linux.go b/libgo/go/net/sock_linux.go
new file mode 100644
index 00000000000..ec31e803b6f
--- /dev/null
+++ b/libgo/go/net/sock_linux.go
@@ -0,0 +1,25 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Sockets for Linux
+
+package net
+
+import (
+ "syscall"
+)
+
+func setKernelSpecificSockopt(s, f int) {
+ // Allow reuse of recently-used addresses.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+ // Allow broadcast.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+ if f == syscall.AF_INET6 {
+ // using ip, tcp, udp, etc.
+ // allow both protocols even if the OS default is otherwise.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+ }
+}
diff --git a/libgo/go/net/sock_windows.go b/libgo/go/net/sock_windows.go
new file mode 100644
index 00000000000..e17c60b98b6
--- /dev/null
+++ b/libgo/go/net/sock_windows.go
@@ -0,0 +1,25 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Sockets for Windows
+
+package net
+
+import (
+ "syscall"
+)
+
+func setKernelSpecificSockopt(s, f int) {
+ // Allow reuse of recently-used addresses and ports.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
+
+ // Allow broadcast.
+ syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
+
+ if f == syscall.AF_INET6 {
+ // using ip, tcp, udp, etc.
+ // allow both protocols even if the OS default is otherwise.
+ syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
+ }
+}
diff --git a/libgo/go/net/srv_test.go b/libgo/go/net/srv_test.go
index 4dd6089cdd2..f1c7a0ab498 100644
--- a/libgo/go/net/srv_test.go
+++ b/libgo/go/net/srv_test.go
@@ -8,10 +8,17 @@
package net
import (
+ "runtime"
"testing"
)
+var avoidMacFirewall = runtime.GOOS == "darwin"
+
func TestGoogleSRV(t *testing.T) {
+ if testing.Short() || avoidMacFirewall {
+ t.Logf("skipping test to avoid external network")
+ return
+ }
_, addrs, err := LookupSRV("xmpp-server", "tcp", "google.com")
if err != nil {
t.Errorf("failed: %s", err)
diff --git a/libgo/go/net/tcpsock.go b/libgo/go/net/tcpsock.go
index b484be20b46..d9aa7cf19a5 100644
--- a/libgo/go/net/tcpsock.go
+++ b/libgo/go/net/tcpsock.go
@@ -62,8 +62,8 @@ func (a *TCPAddr) toAddr() sockaddr {
// host:port and resolves domain names or port names to
// numeric addresses. A literal IPv6 host address must be
// enclosed in square brackets, as in "[::]:80".
-func ResolveTCPAddr(addr string) (*TCPAddr, os.Error) {
- ip, port, err := hostPortToIP("tcp", addr)
+func ResolveTCPAddr(network, addr string) (*TCPAddr, os.Error) {
+ ip, port, err := hostPortToIP(network, addr)
if err != nil {
return nil, err
}
diff --git a/libgo/go/net/textproto/textproto.go b/libgo/go/net/textproto/textproto.go
index fbfad9d61ce..9f19b5495d1 100644
--- a/libgo/go/net/textproto/textproto.go
+++ b/libgo/go/net/textproto/textproto.go
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The textproto package implements generic support for
-// text-based request/response protocols in the style of
-// HTTP, NNTP, and SMTP.
+// Package textproto implements generic support for text-based request/response
+// protocols in the style of HTTP, NNTP, and SMTP.
//
// The package provides:
//
diff --git a/libgo/go/net/udpsock.go b/libgo/go/net/udpsock.go
index 44d618dab08..67684471b72 100644
--- a/libgo/go/net/udpsock.go
+++ b/libgo/go/net/udpsock.go
@@ -62,8 +62,8 @@ func (a *UDPAddr) toAddr() sockaddr {
// host:port and resolves domain names or port names to
// numeric addresses. A literal IPv6 host address must be
// enclosed in square brackets, as in "[::]:80".
-func ResolveUDPAddr(addr string) (*UDPAddr, os.Error) {
- ip, port, err := hostPortToIP("udp", addr)
+func ResolveUDPAddr(network, addr string) (*UDPAddr, os.Error) {
+ ip, port, err := hostPortToIP(network, addr)
if err != nil {
return nil, err
}