internal/socket: use libc calls on darwin

Use libc calls instead of raw syscalls on Darwin.

Change-Id: I0319ae61e3575e7f76b975b9325c9078ab3440d5
Reviewed-on: https://go-review.googlesource.com/c/149617
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/socket/empty.s b/internal/socket/empty.s
new file mode 100644
index 0000000..bff0231
--- /dev/null
+++ b/internal/socket/empty.s
@@ -0,0 +1,7 @@
+// Copyright 2018 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.
+
+// +build darwin,go1.12
+
+// This exists solely so we can linkname in symbols from syscall.
diff --git a/internal/socket/sys_go1_11_darwin.go b/internal/socket/sys_go1_11_darwin.go
new file mode 100644
index 0000000..02d2b3c
--- /dev/null
+++ b/internal/socket/sys_go1_11_darwin.go
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+// +build !go1.12
+
+package socket
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+	l := uint32(len(b))
+	_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
+	return int(l), errnoErr(errno)
+}
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+	_, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
+	return errnoErr(errno)
+}
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+	n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
+	return int(n), errnoErr(errno)
+}
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+	n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
+	return int(n), errnoErr(errno)
+}
diff --git a/internal/socket/sys_go1_12_darwin.go b/internal/socket/sys_go1_12_darwin.go
new file mode 100644
index 0000000..0999a19
--- /dev/null
+++ b/internal/socket/sys_go1_12_darwin.go
@@ -0,0 +1,42 @@
+// Copyright 2018 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.
+
+// +build go1.12
+
+package socket
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+//go:linkname syscall_getsockopt syscall.getsockopt
+func syscall_getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *uint32) error
+
+func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
+	l := uint32(len(b))
+	err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l)
+	return int(l), err
+}
+
+//go:linkname syscall_setsockopt syscall.setsockopt
+func syscall_setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) error
+
+func setsockopt(s uintptr, level, name int, b []byte) error {
+	return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b)))
+}
+
+//go:linkname syscall_recvmsg syscall.recvmsg
+func syscall_recvmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error)
+
+func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
+	return syscall_recvmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
+}
+
+//go:linkname syscall_sendmsg syscall.sendmsg
+func syscall_sendmsg(s int, msg *syscall.Msghdr, flags int) (n int, err error)
+
+func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
+	return syscall_sendmsg(int(s), (*syscall.Msghdr)(unsafe.Pointer(h)), flags)
+}
diff --git a/internal/socket/sys_unix.go b/internal/socket/sys_unix.go
index 18eba30..0eb7128 100644
--- a/internal/socket/sys_unix.go
+++ b/internal/socket/sys_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux,!s390x,!386 netbsd openbsd
+// +build dragonfly freebsd linux,!s390x,!386 netbsd openbsd
 
 package socket