net: add Source field to OpError

Not only by network, transport-layer intermediaries but by
virtualization stuff in a node, it is hard to identify the root cause of
weird faults without information of packet flows after disaster
happened.

This change adds Source field to OpError to be able to represent a
5-tuple of internet transport protocols for helping dealing with
complicated systems.

Also clarifies the usage of Source and Addr fields.

Updates #4856.

Change-Id: I96a523fe391ed14406bfb21604c461d4aac2fa19
Reviewed-on: https://go-review.googlesource.com/9231
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/net/udpsock_plan9.go b/src/net/udpsock_plan9.go
index 8acbb20..949f666 100644
--- a/src/net/udpsock_plan9.go
+++ b/src/net/udpsock_plan9.go
@@ -33,10 +33,10 @@
 	buf := make([]byte, udpHeaderSize+len(b))
 	m, err := c.fd.data.Read(buf)
 	if err != nil {
-		return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: err}
+		return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
 	}
 	if m < udpHeaderSize {
-		return 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: errors.New("short read reading UDP header")}
+		return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: errors.New("short read reading UDP header")}
 	}
 	buf = buf[:m]
 
@@ -59,7 +59,7 @@
 // flags that were set on the packet and the source address of the
 // packet.
 func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
-	return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.net, Addr: c.fd.laddr, Err: syscall.EPLAN9}
+	return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
 }
 
 // WriteToUDP writes a UDP packet to addr via c, copying the payload
@@ -74,7 +74,7 @@
 		return 0, syscall.EINVAL
 	}
 	if addr == nil {
-		return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: nil, Err: errMissingAddress}
+		return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: errMissingAddress}
 	}
 	h := new(udpHeader)
 	h.raddr = addr.IP.To16()
@@ -87,7 +87,7 @@
 	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, Addr: addr, Err: err}
+		return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: err}
 	}
 	return len(b), nil
 }
@@ -99,7 +99,7 @@
 	}
 	a, ok := addr.(*UDPAddr)
 	if !ok {
-		return 0, &OpError{Op: "write", Net: c.fd.dir, Addr: addr, Err: syscall.EINVAL}
+		return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
 	}
 	return c.WriteToUDP(b, a)
 }
@@ -110,7 +110,7 @@
 // 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, Addr: addr, Err: syscall.EPLAN9}
+	return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EPLAN9}
 }
 
 // DialUDP connects to the remote address raddr on the network net,
@@ -127,10 +127,10 @@
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: UnknownNetworkError(net)}
 	}
 	if raddr == nil {
-		return nil, &OpError{"dial", net, nil, errMissingAddress}
+		return nil, &OpError{Op: "dial", Net: net, Source: laddr, Addr: raddr, Err: errMissingAddress}
 	}
 	fd, err := dialPlan9(net, laddr, raddr)
 	if err != nil {
@@ -178,7 +178,7 @@
 	switch net {
 	case "udp", "udp4", "udp6":
 	default:
-		return nil, UnknownNetworkError(net)
+		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: UnknownNetworkError(net)}
 	}
 	if laddr == nil {
 		laddr = &UDPAddr{}
@@ -189,11 +189,11 @@
 	}
 	_, err = l.ctl.WriteString("headers")
 	if err != nil {
-		return nil, err
+		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
 	}
 	l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
 	if err != nil {
-		return nil, err
+		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
 	}
 	fd, err := l.netFD()
 	return newUDPConn(fd), err
@@ -204,5 +204,5 @@
 // interface to join.  ListenMulticastUDP uses default multicast
 // interface if ifi is nil.
 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
-	return nil, syscall.EPLAN9
+	return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: gaddr, Err: syscall.EPLAN9}
 }