]> Cypherpunks repositories - gostls13.git/commitdiff
net: don't return non-nil interface values as Source, Addr in OpError
authorMikio Hara <mikioh.mikioh@gmail.com>
Fri, 29 May 2015 22:33:16 +0000 (07:33 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Sat, 13 Jun 2015 23:39:03 +0000 (23:39 +0000)
Fixes #10992.

Change-Id: Ia376e4de118993b43e5813da57ab25fea8122048
Reviewed-on: https://go-review.googlesource.com/10476
Reviewed-by: Ian Lance Taylor <iant@golang.org>
14 files changed:
src/net/error_test.go
src/net/iprawsock.go
src/net/iprawsock_plan9.go
src/net/iprawsock_posix.go
src/net/ipsock_plan9.go
src/net/tcpsock.go
src/net/tcpsock_plan9.go
src/net/tcpsock_posix.go
src/net/udpsock.go
src/net/udpsock_plan9.go
src/net/udpsock_posix.go
src/net/unixsock.go
src/net/unixsock_plan9.go
src/net/unixsock_posix.go

index 772e0c7f5f0558655dfe989c4f332f4671b71a37..e01b58e6c5e490f09eee2248977203d8e82a3823 100644 (file)
@@ -23,12 +23,38 @@ func (e *OpError) isValid() error {
                return fmt.Errorf("OpError.Net is empty: %v", e)
        }
        for _, addr := range []Addr{e.Source, e.Addr} {
-               if addr != nil {
-                       switch addr.(type) {
-                       case *TCPAddr, *UDPAddr, *IPAddr, *IPNet, *UnixAddr, *pipeAddr, fileAddr:
-                       default:
-                               return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
+               switch addr := addr.(type) {
+               case nil:
+               case *TCPAddr:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
                        }
+               case *UDPAddr:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
+                       }
+               case *IPAddr:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
+                       }
+               case *IPNet:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
+                       }
+               case *UnixAddr:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
+                       }
+               case *pipeAddr:
+                       if addr == nil {
+                               return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
+                       }
+               case fileAddr:
+                       if addr == "" {
+                               return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
+                       }
+               default:
+                       return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
                }
        }
        if e.Err == nil {
@@ -133,6 +159,35 @@ func TestDialError(t *testing.T) {
        }
 }
 
+func TestProtocolDialError(t *testing.T) {
+       switch runtime.GOOS {
+       case "nacl":
+               t.Skipf("not supported on %s", runtime.GOOS)
+       }
+
+       for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
+               var err error
+               switch network {
+               case "tcp":
+                       _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
+               case "udp":
+                       _, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
+               case "ip:4294967296":
+                       _, err = DialIP(network, nil, nil)
+               case "unix", "unixpacket", "unixgram":
+                       _, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
+               }
+               if err == nil {
+                       t.Errorf("%s: should fail", network)
+                       continue
+               }
+               if err = parseDialError(err); err != nil {
+                       t.Errorf("%s: %v", network, err)
+                       continue
+               }
+       }
+}
+
 var listenErrorTests = []struct {
        network, address string
 }{
@@ -222,6 +277,37 @@ func TestListenPacketError(t *testing.T) {
        }
 }
 
+func TestProtocolListenError(t *testing.T) {
+       switch runtime.GOOS {
+       case "nacl", "plan9":
+               t.Skipf("not supported on %s", runtime.GOOS)
+       }
+
+       for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
+               var err error
+               switch network {
+               case "tcp":
+                       _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
+               case "udp":
+                       _, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
+               case "ip:4294967296":
+                       _, err = ListenIP(network, nil)
+               case "unix", "unixpacket":
+                       _, err = ListenUnix(network, &UnixAddr{Name: "//"})
+               case "unixgram":
+                       _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
+               }
+               if err == nil {
+                       t.Errorf("%s: should fail", network)
+                       continue
+               }
+               if err = parseDialError(err); err != nil {
+                       t.Errorf("%s: %v", network, err)
+                       continue
+               }
+       }
+}
+
 // parseReadError parses nestedErr and reports whether it is a valid
 // error value from Read functions.
 // It returns nil when nestedErr is valid.
index 782561a4184ae7a16b6eef2fdfa37b955b42b8bb..71d1fc1fc29363556fa25502a7dde980df990579 100644 (file)
@@ -30,6 +30,13 @@ func (a *IPAddr) isWildcard() bool {
        return a.IP.IsUnspecified()
 }
 
+func (a *IPAddr) opAddr() Addr {
+       if a == nil {
+               return nil
+       }
+       return a
+}
+
 // ResolveIPAddr parses addr as an IP address of the form "host" or
 // "ipv6-host%zone" and resolves the domain name on the network net,
 // which must be "ip", "ip4" or "ip6".
index 079629064e59bb5001636a2f61dc304571a86a2d..b027adc53a7567f7f777673426a6d24ea913e841 100644 (file)
@@ -47,7 +47,7 @@ func (c *IPConn) ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err
 // SetWriteDeadline.  On packet-oriented connections, write timeouts
 // are rare.
 func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // WriteTo implements the PacketConn WriteTo method.
@@ -59,7 +59,7 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (int, error) {
 // b and the associated out-of-band data from oob.  It returns the
 // number of payload and out-of-band bytes written.
 func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // DialIP connects to the remote address raddr on the network protocol
@@ -70,7 +70,7 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 }
 
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
-       return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // ListenIP listens for incoming IP packets addressed to the local
@@ -78,5 +78,5 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 // methods can be used to receive and send IP packets with per-packet
 // addressing.
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
-       return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: syscall.EPLAN9}
 }
index 1102823ef656efaf0615ef88c07dc5f5ff266671..9417606ce9487464ee91a217b62b01b8db2596bc 100644 (file)
@@ -147,18 +147,18 @@ func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
        }
        sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return n, err
 }
@@ -183,19 +183,19 @@ func (c *IPConn) WriteMsgIP(b, oob []byte, addr *IPAddr) (n, oobn int, err error
                return 0, 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
        }
        var sa syscall.Sockaddr
        sa, err = addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return
 }
@@ -210,19 +210,19 @@ func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error) {
 func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn, error) {
        net, proto, err := parseNetwork(netProto)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
        }
        switch net {
        case "ip", "ip4", "ip6":
        default:
-               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: UnknownNetworkError(netProto)}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(netProto)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
        }
        fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial")
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
        }
        return newIPConn(fd), nil
 }
@@ -234,16 +234,16 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
        net, proto, err := parseNetwork(netProto)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: netProto, Source: nil, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
        }
        switch net {
        case "ip", "ip4", "ip6":
        default:
-               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: UnknownNetworkError(netProto)}
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(netProto)}
        }
        fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen")
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
        }
        return newIPConn(fd), nil
 }
index 72d640d9238e681b478e033f09f27843d9f8fd45..9da6ec3053b4ee2a4cf554d1de6a50575c14b868 100644 (file)
@@ -140,6 +140,24 @@ func netErr(e error) {
        if !ok {
                return
        }
+       nonNilInterface := func(a Addr) bool {
+               switch a := a.(type) {
+               case *TCPAddr:
+                       return a == nil
+               case *UDPAddr:
+                       return a == nil
+               case *IPAddr:
+                       return a == nil
+               default:
+                       return false
+               }
+       }
+       if nonNilInterface(oe.Source) {
+               oe.Source = nil
+       }
+       if nonNilInterface(oe.Addr) {
+               oe.Addr = nil
+       }
        if pe, ok := oe.Err.(*os.PathError); ok {
                if _, ok = pe.Err.(syscall.ErrorString); ok {
                        oe.Err = pe.Err
index b7c95b2b943c15c8fbf9f043d4368911a1f4bdeb..8765affd4620edf055fec4788614672f0a6aa738 100644 (file)
@@ -32,6 +32,13 @@ func (a *TCPAddr) isWildcard() bool {
        return a.IP.IsUnspecified()
 }
 
+func (a *TCPAddr) opAddr() Addr {
+       if a == nil {
+               return nil
+       }
+       return a
+}
+
 // ResolveTCPAddr parses addr as a TCP address of the form "host:port"
 // or "[ipv6-host%zone]:port" and resolves a pair of domain name and
 // port name on the network net, which must be "tcp", "tcp4" or
index bc3f8fc4dd12fc8e5307ef2903e51702e2fb7090..9f23703abb4325ce4705fdd1c86c8c9dc460fb0e 100644 (file)
@@ -117,10 +117,10 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
        }
        fd, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -218,7 +218,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &TCPAddr{}
index 51a8e97915136ad8d3f2d83bea9ed31d953906b3..eff77639009b4db23268270c7dba97d5ea513b49 100644 (file)
@@ -159,10 +159,10 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
        }
        return dialTCP(net, laddr, raddr, noDeadline)
 }
@@ -202,7 +202,7 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
        }
 
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
        }
        return newTCPConn(fd), nil
 }
@@ -316,7 +316,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
        switch net {
        case "tcp", "tcp4", "tcp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &TCPAddr{}
index 5291a3e112ad1dc10874d63469abb8d0ede2c79e..9292133aeb8de6e3fcd9b9f15fc3817b62218d4d 100644 (file)
@@ -32,6 +32,13 @@ func (a *UDPAddr) isWildcard() bool {
        return a.IP.IsUnspecified()
 }
 
+func (a *UDPAddr) opAddr() Addr {
+       if a == nil {
+               return nil
+       }
+       return a
+}
+
 // ResolveUDPAddr parses addr as a UDP address of the form "host:port"
 // or "[ipv6-host%zone]:port" and resolves a pair of domain name and
 // port name on the network net, which must be "udp", "udp4" or
index 7bbcf6e4cbc2f71bbdf8b9754b4fc92f8ead4785..1ba57a227e952dcb5ed5aecce3c97d19d082d955 100644 (file)
@@ -74,7 +74,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
        }
        h := new(udpHeader)
        h.raddr = addr.IP.To16()
@@ -87,7 +87,7 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
        i := copy(buf, h.Bytes())
        copy(buf[i:], b)
        if _, err := c.fd.data.Write(buf); err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return len(b), nil
 }
@@ -110,7 +110,7 @@ func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
 // out-of-band data is copied from oob.  It returns the number of
 // payload and out-of-band bytes written.
 func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // DialUDP connects to the remote address raddr on the network net,
@@ -127,10 +127,10 @@ func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, e
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
        }
        fd, err := dialPlan9(net, laddr, raddr)
        if err != nil {
@@ -178,7 +178,7 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &UDPAddr{}
@@ -211,5 +211,5 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 // applications. There are golang.org/x/net/ipv4 and
 // golang.org/x/net/ipv6 packages for general purpose uses.
 func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
-       return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: syscall.EPLAN9}
 }
index 36ada176a16714f03e51ad854a7e3c89aca035f4..61868c4b0cfc2a39c1daa75ad7b1fcb9cb9370df 100644 (file)
@@ -118,18 +118,18 @@ func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
        }
        sa, err := addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return n, err
 }
@@ -156,19 +156,19 @@ func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er
                return 0, 0, syscall.EINVAL
        }
        if c.fd.isConnected && addr != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        if !c.fd.isConnected && addr == nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: errMissingAddress}
        }
        var sa syscall.Sockaddr
        sa, err = addr.sockaddr(c.fd.family)
        if err != nil {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return
 }
@@ -180,10 +180,10 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if raddr == nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
        }
        return dialUDP(net, laddr, raddr, noDeadline)
 }
@@ -191,7 +191,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
 func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
        fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial")
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
        }
        return newUDPConn(fd), nil
 }
@@ -207,7 +207,7 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
        switch net {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
                laddr = &UDPAddr{}
@@ -234,10 +234,10 @@ func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPCon
        switch network {
        case "udp", "udp4", "udp6":
        default:
-               return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr, Err: UnknownNetworkError(network)}
+               return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: UnknownNetworkError(network)}
        }
        if gaddr == nil || gaddr.IP == nil {
-               return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: errMissingAddress}
        }
        fd, err := internetSocket(network, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
        if err != nil {
index 94c4c39ddc542cb7640888d528873b76f080abca..eb91d0d630970ebee608f7b287f9fb09a347b0a9 100644 (file)
@@ -23,6 +23,17 @@ func (a *UnixAddr) String() string {
        return a.Name
 }
 
+func (a *UnixAddr) isWildcard() bool {
+       return a == nil || a.Name == ""
+}
+
+func (a *UnixAddr) opAddr() Addr {
+       if a == nil {
+               return nil
+       }
+       return a
+}
+
 // ResolveUnixAddr parses addr as a Unix domain socket address.
 // The string net gives the network name, "unix", "unixgram" or
 // "unixpacket".
index c31907b0be2daa7bbe55a16e1c0201b5de416667..84b6b600f669e1d1c494e835bc18b7353fffb398 100644 (file)
@@ -47,7 +47,7 @@ func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAdd
 // SetWriteDeadline.  On packet-oriented connections, write timeouts
 // are rare.
 func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
-       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
+       return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // WriteTo implements the PacketConn WriteTo method.
@@ -59,7 +59,7 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
 // from b and the associated out-of-band data from oob.  It returns
 // the number of payload and out-of-band bytes written.
 func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
-       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
+       return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // CloseRead shuts down the reading side of the Unix domain connection.
@@ -82,7 +82,7 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
 }
 
 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
-       return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // UnixListener is a Unix domain socket listener.  Clients should
@@ -95,7 +95,7 @@ type UnixListener struct {
 // ListenUnix announces on the Unix domain socket laddr and returns a
 // Unix listener.  The network net must be "unix" or "unixpacket".
 func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
-       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: syscall.EPLAN9}
 }
 
 // AcceptUnix accepts the next incoming call and returns the new
@@ -143,5 +143,5 @@ func (l *UnixListener) File() (*os.File, error) {
 // The returned connection's ReadFrom and WriteTo methods can be used
 // to receive and send packets with per-packet addressing.
 func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
-       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: syscall.EPLAN9}
+       return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: syscall.EPLAN9}
 }
index 005d2486a858e583e0c4d3d332222d7db66a5827..351d9b3a39ae6b6e54c4c2ff8ad95c5bc53d95c0 100644 (file)
@@ -87,10 +87,6 @@ func (a *UnixAddr) family() int {
        return syscall.AF_UNIX
 }
 
-func (a *UnixAddr) isWildcard() bool {
-       return a == nil || a.Name == ""
-}
-
 func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
        if a == nil {
                return nil, nil
@@ -175,18 +171,18 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error) {
                return 0, syscall.EINVAL
        }
        if c.fd.isConnected {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        if addr == nil {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
        }
        if addr.Net != sotypeToNet(c.fd.sotype) {
-               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EAFNOSUPPORT}
+               return 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EAFNOSUPPORT}
        }
        sa := &syscall.SockaddrUnix{Name: addr.Name}
        n, err := c.fd.writeTo(b, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return n, err
 }
@@ -211,18 +207,18 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err
                return 0, 0, syscall.EINVAL
        }
        if c.fd.sotype == syscall.SOCK_DGRAM && c.fd.isConnected {
-               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: ErrWriteToConnected}
+               return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: ErrWriteToConnected}
        }
        var sa syscall.Sockaddr
        if addr != nil {
                if addr.Net != sotypeToNet(c.fd.sotype) {
-                       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: syscall.EAFNOSUPPORT}
+                       return 0, 0, &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EAFNOSUPPORT}
                }
                sa = &syscall.SockaddrUnix{Name: addr.Name}
        }
        n, oobn, err = c.fd.writeMsg(b, oob, sa)
        if err != nil {
-               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr, Err: err}
+               err = &OpError{Op: "write", Net: c.fd.net, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
        }
        return
 }
@@ -260,7 +256,7 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
        switch net {
        case "unix", "unixgram", "unixpacket":
        default:
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        return dialUnix(net, laddr, raddr, noDeadline)
 }
@@ -268,7 +264,7 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
 func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn, error) {
        fd, err := unixSocket(net, laddr, raddr, "dial", deadline)
        if err != nil {
-               return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: err}
+               return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
        }
        return newUnixConn(fd), nil
 }
@@ -287,14 +283,14 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
        switch net {
        case "unix", "unixpacket":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: errMissingAddress}
        }
        fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
        }
        return &UnixListener{fd: fd, path: fd.laddr.String()}, nil
 }
@@ -389,14 +385,14 @@ func ListenUnixgram(net string, laddr *UnixAddr) (*UnixConn, error) {
        switch net {
        case "unixgram":
        default:
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
        }
        if laddr == nil {
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: errMissingAddress}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: errMissingAddress}
        }
        fd, err := unixSocket(net, laddr, nil, "listen", noDeadline)
        if err != nil {
-               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
+               return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
        }
        return newUnixConn(fd), nil
 }