From: Mikio Hara Date: Wed, 2 Apr 2014 10:42:05 +0000 (+0900) Subject: net: make WriteTo, WriteToUnix and WriteMsgUnix fail when connectionless-mode UnixCon... X-Git-Tag: go1.3beta1~219 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=67a5181045d1601820ea98dff06832339e19fd16;p=gostls13.git net: make WriteTo, WriteToUnix and WriteMsgUnix fail when connectionless-mode UnixConn is already connected This CL tries to fill the gap between Linux and other Unix-like systems in the same way UDPConn already did. Fixes #7677. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/83330045 --- diff --git a/src/pkg/net/unix_test.go b/src/pkg/net/unix_test.go index 91df3ff887..24b6bf9da7 100644 --- a/src/pkg/net/unix_test.go +++ b/src/pkg/net/unix_test.go @@ -151,6 +151,73 @@ func TestUnixAutobindClose(t *testing.T) { ln.Close() } +func TestUnixgramWrite(t *testing.T) { + addr := testUnixAddr() + laddr, err := ResolveUnixAddr("unixgram", addr) + if err != nil { + t.Fatalf("ResolveUnixAddr failed: %v", err) + } + c, err := ListenPacket("unixgram", addr) + if err != nil { + t.Fatalf("ListenPacket failed: %v", err) + } + defer os.Remove(addr) + defer c.Close() + + testUnixgramWriteConn(t, laddr) + testUnixgramWritePacketConn(t, laddr) +} + +func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) { + c, err := Dial("unixgram", raddr.String()) + if err != nil { + t.Fatalf("Dial failed: %v", err) + } + defer c.Close() + + if _, err := c.(*UnixConn).WriteToUnix([]byte("Connection-oriented mode socket"), raddr); err == nil { + t.Fatal("WriteToUnix should fail") + } else if err.(*OpError).Err != ErrWriteToConnected { + t.Fatalf("WriteToUnix should fail as ErrWriteToConnected: %v", err) + } + if _, err = c.(*UnixConn).WriteTo([]byte("Connection-oriented mode socket"), raddr); err == nil { + t.Fatal("WriteTo should fail") + } else if err.(*OpError).Err != ErrWriteToConnected { + t.Fatalf("WriteTo should fail as ErrWriteToConnected: %v", err) + } + if _, _, err = c.(*UnixConn).WriteMsgUnix([]byte("Connection-oriented mode socket"), nil, raddr); err == nil { + t.Fatal("WriteTo should fail") + } else if err.(*OpError).Err != ErrWriteToConnected { + t.Fatalf("WriteMsgUnix should fail as ErrWriteToConnected: %v", err) + } + if _, err := c.Write([]byte("Connection-oriented mode socket")); err != nil { + t.Fatalf("Write failed: %v", err) + } +} + +func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) { + addr := testUnixAddr() + c, err := ListenPacket("unixgram", addr) + if err != nil { + t.Fatalf("ListenPacket failed: %v", err) + } + defer os.Remove(addr) + defer c.Close() + + if _, err := c.(*UnixConn).WriteToUnix([]byte("Connectionless mode socket"), raddr); err != nil { + t.Fatalf("WriteToUnix failed: %v", err) + } + if _, err := c.WriteTo([]byte("Connectionless mode socket"), raddr); err != nil { + t.Fatalf("WriteTo failed: %v", err) + } + if _, _, err := c.(*UnixConn).WriteMsgUnix([]byte("Connectionless mode socket"), nil, raddr); err != nil { + t.Fatalf("WriteMsgUnix failed: %v", err) + } + if _, err := c.(*UnixConn).Write([]byte("Connectionless mode socket")); err == nil { + t.Fatal("Write should fail") + } +} + func TestUnixConnLocalAndRemoteNames(t *testing.T) { for _, laddr := range []string{"", testUnixAddr()} { laddr := laddr diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go index 83f7c3f979..a5f8d0c762 100644 --- a/src/pkg/net/unixsock_posix.go +++ b/src/pkg/net/unixsock_posix.go @@ -171,6 +171,9 @@ func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) { if !c.ok() { return 0, syscall.EINVAL } + if c.fd.isConnected { + return 0, &OpError{Op: "write", Net: c.fd.net, Addr: addr, Err: ErrWriteToConnected} + } if addr == nil { return 0, &OpError{Op: "write", Net: c.fd.net, Addr: nil, Err: errMissingAddress} } @@ -200,6 +203,9 @@ func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err if !c.ok() { 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, Addr: addr, Err: ErrWriteToConnected} + } if addr != nil { if addr.Net != sotypeToNet(c.fd.sotype) { return 0, 0, syscall.EAFNOSUPPORT