[netboot] Use RawConn in NewLogListener

A suggested refactoring of raggi@'s to tidy up the locking, CloseOnExec,
and file descriptor logic.

Test: successfully listened locally.

Change-Id: Idd8a99a728b73c93d24674730e09879346dc9946
diff --git a/netboot/loglistener.go b/netboot/loglistener.go
index 96a9661..982232a 100644
--- a/netboot/loglistener.go
+++ b/netboot/loglistener.go
@@ -9,8 +9,8 @@
 	"bytes"
 	"encoding/binary"
 	"errors"
+	"fmt"
 	"net"
-	"os"
 	"syscall"
 
 	"golang.org/x/sys/unix"
@@ -37,45 +37,41 @@
 // LogListener is Zircon's debug log listener.
 type LogListener struct {
 	seq      uint32
-	conn     net.PacketConn
+	conn     *net.UDPConn
 	nodename string
 }
 
 // NewLogListener creates and connects a new instance of debug log listener.
 func NewLogListener(nodename string) (*LogListener, error) {
-	syscall.ForkLock.RLock()
-	fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
-	if err == nil {
-		unix.CloseOnExec(fd)
+	conn, err := net.ListenUDP("udp6", &net.UDPAddr{
+		IP:   net.IPv6zero,
+		Port: debugPort,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("failed to bind to udp6 port: %v\n", err)
 	}
-	syscall.ForkLock.RUnlock()
+
+	rawConn, err := conn.SyscallConn()
 	if err != nil {
 		return nil, err
 	}
 
 	// SO_REUSEADDR and SO_REUSEPORT allows binding to the same port multiple
 	// times which is necessary in the case when there are multiple instances.
-	if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
-		syscall.Close(fd)
+	var fderr error
+	if err = rawConn.Control(func(fd uintptr) {
+		if fderr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEADDR, 1); fderr != nil {
+			return
+		}
+
+		if fderr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); fderr != nil {
+			return
+		}
+	}); err != nil {
 		return nil, err
 	}
-
-	if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	// Bind the socket to the default debug log listener port.
-	if err := syscall.Bind(fd, &syscall.SockaddrInet6{Port: debugPort}); err != nil {
-		syscall.Close(fd)
-		return nil, err
-	}
-
-	f := os.NewFile(uintptr(fd), "")
-	conn, err := net.FilePacketConn(f)
-	f.Close()
-	if err != nil {
-		return nil, err
+	if fderr != nil {
+		return nil, fderr
 	}
 
 	return &LogListener{