net: permit WriteMsgUDP to connected UDP sockets

The sanity checks at the beginning of WriteMsgUDP were too
strict, and did not allow a case sendmsg(2) suppports: sending
to a connected UDP socket.

This fixes the sanity checks. Either the socket is unconnected,
and a destination addresses is required (what all existing callers
must have been doing), or the socket is connected and an explicit
destination address must not be used.

Fixes #9807

Change-Id: I08d4ec3c2bf830335c402acfc0680c841cfcec71
Reviewed-on: https://go-review.googlesource.com/3951
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
diff --git a/src/net/udp_test.go b/src/net/udp_test.go
index 125bbca..d291b26 100644
--- a/src/net/udp_test.go
+++ b/src/net/udp_test.go
@@ -81,26 +81,26 @@
 		t.Skipf("skipping test on %q", runtime.GOOS)
 	}
 
-	l, err := ListenPacket("udp", "127.0.0.1:0")
+	c, err := ListenPacket("udp", "127.0.0.1:0")
 	if err != nil {
-		t.Fatalf("Listen failed: %v", err)
+		t.Fatal(err)
 	}
-	defer l.Close()
+	defer c.Close()
 
-	testWriteToConn(t, l.LocalAddr().String())
-	testWriteToPacketConn(t, l.LocalAddr().String())
+	testWriteToConn(t, c.LocalAddr().String())
+	testWriteToPacketConn(t, c.LocalAddr().String())
 }
 
 func testWriteToConn(t *testing.T, raddr string) {
 	c, err := Dial("udp", raddr)
 	if err != nil {
-		t.Fatalf("Dial failed: %v", err)
+		t.Fatal(err)
 	}
 	defer c.Close()
 
 	ra, err := ResolveUDPAddr("udp", raddr)
 	if err != nil {
-		t.Fatalf("ResolveUDPAddr failed: %v", err)
+		t.Fatal(err)
 	}
 
 	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-oriented mode socket"), ra)
@@ -121,36 +121,60 @@
 
 	_, err = c.Write([]byte("Connection-oriented mode socket"))
 	if err != nil {
-		t.Fatalf("Write failed: %v", err)
+		t.Fatal(err)
+	}
+
+	_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-oriented mode socket"), nil, ra)
+	if err == nil {
+		t.Fatal("WriteMsgUDP should fail")
+	}
+	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
+		t.Fatalf("WriteMsgUDP should fail as ErrWriteToConnected: %v", err)
+	}
+	_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-oriented mode socket"), nil, nil)
+	if err != nil {
+		t.Fatal(err)
 	}
 }
 
 func testWriteToPacketConn(t *testing.T, raddr string) {
 	c, err := ListenPacket("udp", "127.0.0.1:0")
 	if err != nil {
-		t.Fatalf("ListenPacket failed: %v", err)
+		t.Fatal(err)
 	}
 	defer c.Close()
 
 	ra, err := ResolveUDPAddr("udp", raddr)
 	if err != nil {
-		t.Fatalf("ResolveUDPAddr failed: %v", err)
+		t.Fatal(err)
 	}
 
 	_, err = c.(*UDPConn).WriteToUDP([]byte("Connection-less mode socket"), ra)
 	if err != nil {
-		t.Fatalf("WriteToUDP failed: %v", err)
+		t.Fatal(err)
 	}
 
 	_, err = c.WriteTo([]byte("Connection-less mode socket"), ra)
 	if err != nil {
-		t.Fatalf("WriteTo failed: %v", err)
+		t.Fatal(err)
 	}
 
 	_, err = c.(*UDPConn).Write([]byte("Connection-less mode socket"))
 	if err == nil {
 		t.Fatal("Write should fail")
 	}
+
+	_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-less mode socket"), nil, nil)
+	if err == nil {
+		t.Fatal("WriteMsgUDP should fail")
+	}
+	if err != nil && err.(*OpError).Err != errMissingAddress {
+		t.Fatalf("WriteMsgUDP should fail as errMissingAddress: %v", err)
+	}
+	_, _, err = c.(*UDPConn).WriteMsgUDP([]byte("Connection-less mode socket"), nil, ra)
+	if err != nil {
+		t.Fatal(err)
+	}
 }
 
 var udpConnLocalNameTests = []struct {