func RemoteRecvCredentials(conn *net.UnixConn) (uint32, uint32, error) { err := syscall.SetsockoptInt(sysfd(conn), syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1) if err != nil { return 0, 0, err } oob := make([]byte, len(syscall.UnixCredentials(&syscall.Ucred{}))) _, _, _, _, err = conn.ReadMsgUnix(nil, oob) if err != nil { return 0, 0, err } scm, err := syscall.ParseSocketControlMessage(oob) if err != nil { return 0, 0, err } ucred, err := syscall.ParseUnixCredentials(&scm[0]) if err != nil { return 0, 0, err } return ucred.Uid, ucred.Gid, nil }
func (fd *Fd) readFrom(c *net.UnixConn) error { var b []byte oob := make([]byte, 16) _, oobn, _, _, err := c.ReadMsgUnix(b, oob) if err != nil { return err } if oobn == 0 { return errors.New("error reading oob") } oob = oob[:oobn] scms, err := syscall.ParseSocketControlMessage(oob) if err != nil { return err } if len(scms) != 1 { return fmt.Errorf("expected 1 SocketControlMessage, got %d", len(scms)) } scm := scms[0] fds, err := syscall.ParseUnixRights(&scm) if err != nil { return nil } if len(fds) != 1 { return fmt.Errorf("expected 1 fd, got %d", len(fds)) } *fd = Fd(fds[0]) return nil }
func receiveUnix(conn *net.UnixConn) ([]byte, []int, error) { buf := make([]byte, 4096) oob := make([]byte, 4096) bufn, oobn, _, _, err := conn.ReadMsgUnix(buf, oob) if err != nil { return nil, nil, err } return buf[:bufn], extractFds(oob[:oobn]), nil }
func readRequest(c *net.UnixConn) (*Request, error) { var l uint32 err := binary.Read(c, binary.BigEndian, &l) length := int(l) if err != nil { return nil, err } payload := make([]byte, length) n, err := c.Read(payload) if err != nil { return nil, err } else if n != length { return nil, fmt.Errorf("Payload was %d bytes rather than reported size of %d", n, length) } req := &Request{} err = json.Unmarshal(payload, req) if err != nil { return nil, err } if !req.HasFds { return req, nil } payload = make([]byte, 1) // TODO: does this buffer need to be configurable? oob := make([]byte, 8192) n, oobn, _, _, err := c.ReadMsgUnix(payload, oob) if err != nil && err != io.EOF { return nil, err } if n != 1 { return nil, fmt.Errorf("Error reading OOB filedescriptors") } oob = oob[0:oobn] scm, err := syscall.ParseSocketControlMessage(oob) if err != nil { return nil, fmt.Errorf("Error parsing socket control message: %v", err) } var fds []int for i := 0; i < len(scm); i++ { tfds, err := syscall.ParseUnixRights(&scm[i]) if err == syscall.EINVAL { continue // Wasn't a UnixRights Control Message } else if err != nil { return nil, fmt.Errorf("Error parsing unix rights: %v", err) } fds = append(fds, tfds...) } if len(fds) == 0 { return nil, fmt.Errorf("Failed to receive any FDs on a request with HasFds == true") } req.ReceivedFds = fds return req, nil }
// Receive File from UnixConn func RecvFD(conn *net.UnixConn) (file *os.File, err error) { cmsgb := make([]byte, CmsgSpace(unsafe.Sizeof(int(0)))) cms := (*syscall.Cmsghdr)(unsafe.Pointer(&cmsgb[0])) cms.Len = CmsgLen(unsafe.Sizeof(int(0))) cms.Level = 1 cms.Type = 1 _, _, _, _, err = conn.ReadMsgUnix([]byte{}, cmsgb) if err != nil { return } fdArea := cmsgb[unsafe.Sizeof(syscall.Cmsghdr{}):] fdnum := uintptr(fdArea[0]) | uintptr(byte(fdArea[1]<<8)) | uintptr(byte(fdArea[2]<<16)) | uintptr(byte(fdArea[3]<<24)) file = os.NewFile(fdnum, "") return }
func ReadWaylandMessage(conn *net.UnixConn) (*Message, error) { var buf [8]byte msg := Message{} control := make([]byte, 24) n, oobn, _, _, err := conn.ReadMsgUnix(buf[:], control) if err != nil { return nil, err } if n != 8 { return nil, errors.New("Unable to read message header.") } if oobn > 0 { if oobn > len(control) { panic("Unsufficient control msg buffer") } msg.control_msgs, err = syscall.ParseSocketControlMessage(control) if err != nil { panic(fmt.Sprintf("Control message parse error: %s", err.Error())) } } msg.Id = ProxyId(binary.LittleEndian.Uint32(buf[0:4])) msg.Opcode = uint32(binary.LittleEndian.Uint16(buf[4:6])) msg.size = uint32(binary.LittleEndian.Uint16(buf[6:8])) // subtract 8 bytes from header data := make([]byte, msg.size-8) n, err = conn.Read(data) if err != nil { return nil, err } if n != int(msg.size)-8 { return nil, errors.New("Invalid message size.") } msg.data = bytes.NewBuffer(data) return &msg, nil }
func ReadFile(c *net.UnixConn, timeout time.Duration) (*os.File, error) { oob := make([]byte, 64) if timeout > 0 { deadline := time.Now().Add(timeout) if err := c.SetReadDeadline(deadline); err != nil { return nil, err } } _, oobn, flags, _, err := c.ReadMsgUnix(nil, oob) if err != nil { return nil, err } if flags != 0 || oobn <= 0 { panic("ReadMsgUnix: flags != 0 || oobn <= 0") } // file descriptors are now open in this process scm, err := syscall.ParseSocketControlMessage(oob[:oobn]) if err != nil { return nil, err } if len(scm) != 1 { panic("invalid scm message") } fds, err := syscall.ParseUnixRights(&scm[0]) if err != nil { return nil, err } if len(fds) != 1 { panic("invalid scm message") } return os.NewFile(uintptr(fds[0]), ""), nil }
func RecvFd(conn *net.UnixConn) (*os.File, error) { buf := make([]byte, 32) oob := make([]byte, 32) _, oobn, _, _, err := conn.ReadMsgUnix(buf, oob) if err != nil { return nil, fmt.Errorf("recvfd: err %v", err) } scms, err := syscall.ParseSocketControlMessage(oob[:oobn]) if err != nil { return nil, fmt.Errorf("recvfd: ParseSocketControlMessage failed %v", err) } if len(scms) != 1 { return nil, fmt.Errorf("recvfd: SocketControlMessage count not 1: %v", len(scms)) } scm := scms[0] fds, err := syscall.ParseUnixRights(&scm) if err != nil { return nil, fmt.Errorf("recvfd: ParseUnixRights failed %v", err) } if len(fds) != 1 { return nil, fmt.Errorf("recvfd: fd count not 1: %v", len(fds)) } return os.NewFile(uintptr(fds[0]), "passed-fd"), nil }