net: Plan 9 support

All tests enabled by default passes except those in timeout_test.go.

For TestLookupPort, add an entry for "bootps" in /lib/ndb/common
(Plan 9 calls it "bootp"). I've sent out a patch to fix this.

R=paulzhol, rsc, mikioh.mikioh
CC=ality, golang-dev
https://golang.org/cl/4779041
diff --git a/src/pkg/net/udpsock_plan9.go b/src/pkg/net/udpsock_plan9.go
new file mode 100644
index 0000000..bb71960
--- /dev/null
+++ b/src/pkg/net/udpsock_plan9.go
@@ -0,0 +1,187 @@
+// Copyright 2009 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.
+
+// UDP for Plan 9
+
+package net
+
+import (
+	"os"
+)
+
+// UDPConn is the implementation of the Conn and PacketConn
+// interfaces for UDP network connections.
+type UDPConn struct {
+	plan9Conn
+}
+
+// UDP-specific methods.
+
+// ReadFromUDP reads a UDP packet from c, copying the payload into b.
+// It returns the number of bytes copied into b and the return address
+// that was on the packet.
+//
+// ReadFromUDP can be made to time out and return an error with Timeout() == true
+// after a fixed time limit; see SetTimeout and SetReadTimeout.
+func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err os.Error) {
+	if !c.ok() {
+		return 0, nil, os.EINVAL
+	}
+	if c.data == nil {
+		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
+		if err != nil {
+			return 0, nil, err
+		}
+	}
+	buf := make([]byte, udpHeaderSize+len(b))
+	m, err := c.data.Read(buf)
+	if err != nil {
+		return
+	}
+	if m < udpHeaderSize {
+		return 0, nil, os.NewError("short read reading UDP header")
+	}
+	buf = buf[:m]
+
+	h, buf := unmarshalUDPHeader(buf)
+	n = copy(b, buf)
+	return n, &UDPAddr{h.raddr, int(h.rport)}, nil
+}
+
+// ReadFrom implements the net.PacketConn ReadFrom method.
+func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err os.Error) {
+	if !c.ok() {
+		return 0, nil, os.EINVAL
+	}
+	return c.ReadFromUDP(b)
+}
+
+// WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
+//
+// WriteToUDP can be made to time out and return
+// an error with Timeout() == true after a fixed time limit;
+// see SetTimeout and SetWriteTimeout.
+// On packet-oriented connections, write timeouts are rare.
+func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err os.Error) {
+	if !c.ok() {
+		return 0, os.EINVAL
+	}
+	if c.data == nil {
+		c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
+		if err != nil {
+			return 0, err
+		}
+	}
+	h := new(udpHeader)
+	h.raddr = addr.IP.To16()
+	h.laddr = c.laddr.(*UDPAddr).IP.To16()
+	h.ifcaddr = IPv6zero // ignored (receive only)
+	h.rport = uint16(addr.Port)
+	h.lport = uint16(c.laddr.(*UDPAddr).Port)
+
+	buf := make([]byte, udpHeaderSize+len(b))
+	i := copy(buf, h.Bytes())
+	copy(buf[i:], b)
+	return c.data.Write(buf)
+}
+
+// WriteTo implements the net.PacketConn WriteTo method.
+func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
+	if !c.ok() {
+		return 0, os.EINVAL
+	}
+	a, ok := addr.(*UDPAddr)
+	if !ok {
+		return 0, &OpError{"writeto", "udp", addr, os.EINVAL}
+	}
+	return c.WriteToUDP(b, a)
+}
+
+// DialUDP connects to the remote address raddr on the network net,
+// which must be "udp", "udp4", or "udp6".  If laddr is not nil, it is used
+// as the local address for the connection.
+func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err os.Error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	if raddr == nil {
+		return nil, &OpError{"dial", "udp", nil, errMissingAddress}
+	}
+	c1, err := dialPlan9(net, laddr, raddr)
+	if err != nil {
+		return
+	}
+	return &UDPConn{*c1}, nil
+}
+
+const udpHeaderSize = 16*3 + 2*2
+
+type udpHeader struct {
+	raddr, laddr, ifcaddr IP
+	rport, lport          uint16
+}
+
+func (h *udpHeader) Bytes() []byte {
+	b := make([]byte, udpHeaderSize)
+	i := 0
+	i += copy(b[i:i+16], h.raddr)
+	i += copy(b[i:i+16], h.laddr)
+	i += copy(b[i:i+16], h.ifcaddr)
+	b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
+	b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
+	return b
+}
+
+func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
+	h := new(udpHeader)
+	h.raddr, b = IP(b[:16]), b[16:]
+	h.laddr, b = IP(b[:16]), b[16:]
+	h.ifcaddr, b = IP(b[:16]), b[16:]
+	h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
+	h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
+	return h, b
+}
+
+// ListenUDP listens for incoming UDP packets addressed to the
+// local address laddr.  The returned connection c's ReadFrom
+// and WriteTo methods can be used to receive and send UDP
+// packets with per-packet addressing.
+func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) {
+	switch net {
+	case "udp", "udp4", "udp6":
+	default:
+		return nil, UnknownNetworkError(net)
+	}
+	if laddr == nil {
+		return nil, &OpError{"listen", "udp", nil, errMissingAddress}
+	}
+	l, err := listenPlan9(net, laddr)
+	if err != nil {
+		return
+	}
+	_, err = l.ctl.WriteString("headers")
+	if err != nil {
+		return
+	}
+	return &UDPConn{*l.plan9Conn()}, nil
+}
+
+// JoinGroup joins the IPv4 multicast group named by addr.
+// The UDPConn must use the "udp4" network.
+func (c *UDPConn) JoinGroup(addr IP) os.Error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return os.EPLAN9
+}
+
+// LeaveGroup exits the IPv4 multicast group named by addr.
+func (c *UDPConn) LeaveGroup(addr IP) os.Error {
+	if !c.ok() {
+		return os.EINVAL
+	}
+	return os.EPLAN9
+}