diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh index 809ab069..60ffa48a 100755 --- a/unix/mkerrors.sh +++ b/unix/mkerrors.sh @@ -115,6 +115,7 @@ includes_FreeBSD=' #include #include #include +#include #include #include #include diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go index e771a3c5..1223d7ae 100644 --- a/unix/syscall_darwin.go +++ b/unix/syscall_darwin.go @@ -382,7 +382,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e // The usual level and opt are SOL_LOCAL and LOCAL_PEERCRED, respectively. func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { x := new(Xucred) - vallen := _Socklen(unsafe.Sizeof(Xucred{})) + vallen := _Socklen(SizeofXucred) err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen) return x, err } diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go index 15af63dd..18c392cf 100644 --- a/unix/syscall_freebsd.go +++ b/unix/syscall_freebsd.go @@ -126,6 +126,15 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) } +// GetsockoptXucred is a getsockopt wrapper that returns an Xucred struct. +// The usual level and opt are SOL_LOCAL and LOCAL_PEERCRED, respectively. +func GetsockoptXucred(fd, level, opt int) (*Xucred, error) { + x := new(Xucred) + vallen := _Socklen(SizeofXucred) + err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen) + return x, err +} + func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny diff --git a/unix/syscall_freebsd_test.go b/unix/syscall_freebsd_test.go index f1b92577..f56d9bcc 100644 --- a/unix/syscall_freebsd_test.go +++ b/unix/syscall_freebsd_test.go @@ -11,6 +11,7 @@ import ( "flag" "fmt" "io/ioutil" + "net" "os" "os/exec" "path" @@ -297,6 +298,42 @@ func TestCapRightsSetAndClear(t *testing.T) { } } +func TestGetsockoptXucred(t *testing.T) { + fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) + if err != nil { + t.Fatalf("Socketpair: %v", err) + } + defer unix.Close(fds[0]) + defer unix.Close(fds[1]) + + srvFile := os.NewFile(uintptr(fds[0]), "server") + defer srvFile.Close() + srv, err := net.FileConn(srvFile) + if err != nil { + t.Fatalf("FileConn: %v", err) + } + defer srv.Close() + + cliFile := os.NewFile(uintptr(fds[1]), "client") + defer cliFile.Close() + cli, err := net.FileConn(cliFile) + if err != nil { + t.Fatalf("FileConn: %v", err) + } + defer cli.Close() + + cred, err := unix.GetsockoptXucred(fds[1], unix.SOL_LOCAL, unix.LOCAL_PEERCRED) + if err == unix.ENOTCONN { + t.Skip("GetsockoptXucred not supported with Socketpair on FreeBSD 11 and earlier") + } else if err != nil { + t.Fatal(err) + } + t.Logf("got: %+v", cred) + if got, want := cred.Uid, os.Getuid(); int(got) != int(want) { + t.Errorf("uid = %v; want %v", got, want) + } +} + // stringsFromByteSlice converts a sequence of attributes to a []string. // On FreeBSD, each entry consists of a single byte containing the length // of the attribute name, followed by the attribute name. diff --git a/unix/types_freebsd.go b/unix/types_freebsd.go index 573f9d8d..968c3b02 100644 --- a/unix/types_freebsd.go +++ b/unix/types_freebsd.go @@ -40,6 +40,7 @@ package unix #include #include #include +#include #include #include #include @@ -204,6 +205,8 @@ type RawSockaddrAny C.struct_sockaddr_any type _Socklen C.socklen_t +type Xucred C.struct_xucred + type Linger C.struct_linger type Iovec C.struct_iovec @@ -230,6 +233,7 @@ const ( SizeofSockaddrAny = C.sizeof_struct_sockaddr_any SizeofSockaddrUnix = C.sizeof_struct_sockaddr_un SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl + SizeofXucred = C.sizeof_struct_xucred SizeofLinger = C.sizeof_struct_linger SizeofIovec = C.sizeof_struct_iovec SizeofIPMreq = C.sizeof_struct_ip_mreq diff --git a/unix/zerrors_freebsd_386.go b/unix/zerrors_freebsd_386.go index 24fdef16..9c7c5e16 100644 --- a/unix/zerrors_freebsd_386.go +++ b/unix/zerrors_freebsd_386.go @@ -998,6 +998,11 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_CREDS_PERSISTENT = 0x3 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1376,6 +1381,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 diff --git a/unix/zerrors_freebsd_amd64.go b/unix/zerrors_freebsd_amd64.go index fede889f..b265abb2 100644 --- a/unix/zerrors_freebsd_amd64.go +++ b/unix/zerrors_freebsd_amd64.go @@ -998,6 +998,11 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_CREDS_PERSISTENT = 0x3 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1377,6 +1382,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 diff --git a/unix/zerrors_freebsd_arm.go b/unix/zerrors_freebsd_arm.go index 6430180f..0326a6b3 100644 --- a/unix/zerrors_freebsd_arm.go +++ b/unix/zerrors_freebsd_arm.go @@ -981,6 +981,11 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_CREDS_PERSISTENT = 0x3 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1342,6 +1347,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 diff --git a/unix/zerrors_freebsd_arm64.go b/unix/zerrors_freebsd_arm64.go index 5a9c21ba..218d3990 100644 --- a/unix/zerrors_freebsd_arm64.go +++ b/unix/zerrors_freebsd_arm64.go @@ -998,6 +998,11 @@ const ( KERN_OSRELEASE = 0x2 KERN_OSTYPE = 0x1 KERN_VERSION = 0x4 + LOCAL_CONNWAIT = 0x4 + LOCAL_CREDS = 0x2 + LOCAL_CREDS_PERSISTENT = 0x3 + LOCAL_PEERCRED = 0x1 + LOCAL_VENDOR = 0x80000000 LOCK_EX = 0x2 LOCK_NB = 0x4 LOCK_SH = 0x1 @@ -1377,6 +1382,7 @@ const ( SOCK_RDM = 0x4 SOCK_SEQPACKET = 0x5 SOCK_STREAM = 0x1 + SOL_LOCAL = 0x0 SOL_SOCKET = 0xffff SOMAXCONN = 0x80 SO_ACCEPTCONN = 0x2 diff --git a/unix/ztypes_freebsd_386.go b/unix/ztypes_freebsd_386.go index a70d2e23..c51bc88f 100644 --- a/unix/ztypes_freebsd_386.go +++ b/unix/ztypes_freebsd_386.go @@ -251,6 +251,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -313,6 +321,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x50 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 diff --git a/unix/ztypes_freebsd_amd64.go b/unix/ztypes_freebsd_amd64.go index 00ce9297..395b6918 100644 --- a/unix/ztypes_freebsd_amd64.go +++ b/unix/ztypes_freebsd_amd64.go @@ -247,6 +247,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -309,6 +317,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x58 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8 diff --git a/unix/ztypes_freebsd_arm.go b/unix/ztypes_freebsd_arm.go index 28694e52..d3f9d254 100644 --- a/unix/ztypes_freebsd_arm.go +++ b/unix/ztypes_freebsd_arm.go @@ -249,6 +249,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -311,6 +319,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x50 SizeofLinger = 0x8 SizeofIovec = 0x8 SizeofIPMreq = 0x8 diff --git a/unix/ztypes_freebsd_arm64.go b/unix/ztypes_freebsd_arm64.go index cb749940..434d6e8e 100644 --- a/unix/ztypes_freebsd_arm64.go +++ b/unix/ztypes_freebsd_arm64.go @@ -247,6 +247,14 @@ type RawSockaddrAny struct { type _Socklen uint32 +type Xucred struct { + Version uint32 + Uid uint32 + Ngroups int16 + Groups [16]uint32 + _ *byte +} + type Linger struct { Onoff int32 Linger int32 @@ -309,6 +317,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x36 + SizeofXucred = 0x58 SizeofLinger = 0x8 SizeofIovec = 0x10 SizeofIPMreq = 0x8