| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- //go:build netbsd
- package localapi
- import (
- "encoding/binary"
- "fmt"
- "net"
- "unsafe"
- "golang.org/x/sys/unix"
- )
- const peerCheckSupported = true
- // NetBSD reports the peer's identity through LOCAL_PEEREID at the SOL_LOCAL level,
- // filling a `struct unpcbid { pid_t unp_pid; uid_t unp_euid; gid_t unp_egid; }`.
- // golang.org/x/sys/unix has no typed wrapper for it, so the getsockopt goes out by hand
- // exactly the way that package's own generated wrappers do on this platform.
- const (
- solLocal = 0
- localPeerEID = 0x0003
- unpcbidSize = 12
- unpcbidEUIDOffs = 4
- )
- // peerUID returns the uid of the process on the other end of conn.
- //
- // Anything unexpected here is an error rather than a default, so a wrong constant or an
- // unsupported kernel refuses connections instead of silently admitting them.
- func peerUID(conn net.Conn) (uid uint32, err error) {
- err = withPeerFD(conn, func(fd int) error {
- var (
- buf [unpcbidSize]byte
- size = uint32(unpcbidSize)
- )
- _, _, errno := unix.Syscall6(
- unix.SYS_GETSOCKOPT,
- uintptr(fd),
- uintptr(solLocal),
- uintptr(localPeerEID),
- uintptr(unsafe.Pointer(&buf[0])),
- uintptr(unsafe.Pointer(&size)),
- 0,
- )
- if errno != 0 {
- return errno
- }
- if size != unpcbidSize {
- return fmt.Errorf("LOCAL_PEEREID returned %d bytes, expected %d", size, unpcbidSize)
- }
- // Read, not cast: the buffer is bytes, and a cast would fault on an
- // architecture that wants the uint32 aligned.
- uid = binary.NativeEndian.Uint32(buf[unpcbidEUIDOffs:])
- return nil
- })
- return uid, err
- }
|