Example #1
0
func SendRequest(c *net.UnixConn, req *server.Request) error {
	payload, err := json.Marshal(req)
	if err != nil {
		return err
	}
	err = binary.Write(c, binary.BigEndian, uint32(len(payload)))
	if err != nil {
		return err
	}
	n, err := c.Write(payload)
	if err != nil {
		return err
	} else if n != len(payload) {
		return fmt.Errorf("Failed to write full payload, expected %v, wrote %v", len(payload), n)
	}

	if !req.HasFds {
		return nil
	}
	// Send filedescriptors with a 1 byte message.
	var oob []byte
	oob = syscall.UnixRights(req.Fds...)
	payload = make([]byte, 1)
	n, oobn, err := c.WriteMsgUnix(payload, oob, nil)
	if err != nil {
		return err
	} else if n != len(payload) || oobn != len(oob) {
		return fmt.Errorf("Error writing to socket, expected n=%v got %v, oob=%v got %v", len(payload), n, len(oob), oobn)
	}
	return nil
}
Example #2
0
func writeData(conn *net.UnixConn, files []*os.File, pid int, responseErr error) {
	var errMsg string = ""
	if responseErr != nil {
		errMsg = responseErr.Error()
	}
	response := &Response{
		Pid:        pid,
		ErrMessage: errMsg,
	}

	responseJson, _ := json.Marshal(response) // Ignore error

	args := make([]int, len(files))
	for i, f := range files {
		args[i] = int(f.Fd())
	}
	resp := syscall.UnixRights(args...)

	conn.WriteMsgUnix(responseJson, resp, nil) // Ignore error

	// Close the files whose descriptors have been sent to the host to ensure that
	// a close on the host takes effect in a timely fashion.
	for _, file := range files {
		file.Close() // Ignore error
	}
}
Example #3
0
func (t *unixTransport) SendMessage(msg *Message) error {
	fds := make([]int, 0)
	for i, v := range msg.Body {
		if fd, ok := v.(UnixFD); ok {
			msg.Body[i] = UnixFDIndex(len(fds))
			fds = append(fds, int(fd))
		}
	}
	if len(fds) != 0 {
		if !t.hasUnixFDs {
			return errors.New("dbus: unix fd passing not enabled")
		}
		msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds)))
		oob := syscall.UnixRights(fds...)
		buf := new(bytes.Buffer)
		msg.EncodeTo(buf, binary.LittleEndian)
		n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
		if err != nil {
			return err
		}
		if n != buf.Len() || oobn != len(oob) {
			return io.ErrShortWrite
		}
	} else {
		if err := msg.EncodeTo(t, binary.LittleEndian); err != nil {
			return nil
		}
	}
	return nil
}
Example #4
0
func Notify(state string, fds ...int) {
	ns := os.Getenv("NOTIFY_SOCKET")
	if ns == "" {
		return
	}

	addr := &net.UnixAddr{
		Name: ns,
		Net:  "unixgram",
	}

	conn, err := net.DialUnix("unixgram", nil, addr)
	if err != nil {
		return
	}

	defer conn.Close()

	if len(fds) > 0 {
		rights := syscall.UnixRights(fds...)

		conn.WriteMsgUnix([]byte(state), rights, nil)

	} else {
		conn.Write([]byte(state))
	}
}
Example #5
0
func (m *Message) Write(arg interface{}) error {
	switch t := arg.(type) {
	case Proxy:
		return binary.Write(m.data, binary.LittleEndian, uint32(t.Id()))
	case uint32, int32:
		return binary.Write(m.data, binary.LittleEndian, t)
	case float32:
		f := float64ToFixed(float64(t))
		return binary.Write(m.data, binary.LittleEndian, f)
	case string:
		str, _ := arg.(string)
		tail := 4 - (len(str) & 0x3)
		err := binary.Write(m.data, binary.LittleEndian, uint32(len(str)+tail))
		if err != nil {
			return err
		}
		err = binary.Write(m.data, binary.LittleEndian, []byte(str))
		if err != nil {
			return err
		}
		padding := make([]byte, tail)
		return binary.Write(m.data, binary.LittleEndian, padding)
	case uintptr:
		rights := syscall.UnixRights(int(t))
		return binary.Write(m.control, binary.LittleEndian, rights)
	default:
		panic("Invalid Wayland request parameter type.")
	}
	return nil
}
Example #6
0
func (w *FDWriter) Write(b []byte) (int, error) {
	if len(w.fds) == 0 {
		return w.conn.Write(b)
	} else {
		rights := syscall.UnixRights(w.fds...)
		n, _, err := w.conn.WriteMsgUnix(b, rights, nil)
		w.fds = nil
		return n, err
	}
}
Example #7
0
func WriteFile(c *net.UnixConn, file *os.File, timeout time.Duration) error {
	if timeout > 0 {
		deadline := time.Now().Add(timeout)
		if err := c.SetWriteDeadline(deadline); err != nil {
			return err
		}
	}
	oob := syscall.UnixRights(int(file.Fd()))
	_, _, err := c.WriteMsgUnix(nil, oob, nil)
	return err
}
Example #8
0
func (fd Fd) writeTo(c *net.UnixConn) error {
	var b []byte
	oob := syscall.UnixRights(int(fd))
	_, oobn, err := c.WriteMsgUnix(b, oob, nil)
	if err != nil {
		return err
	}
	if oobn != len(oob) {
		return fmt.Errorf("expected to write %d oob bytes, wrote %d", len(oob), oobn)
	}
	return nil
}
Example #9
0
func (usock *Usock) WriteFD(fd int) error {
	rights := syscall.UnixRights(fd)

	dummyByte := []byte("\000")
	n, oobn, err := usock.Conn.WriteMsgUnix(dummyByte, rights, nil)
	if err != nil {
		str := fmt.Sprintf("Usock#WriteFD:WriteMsgUnix: %v %v\n", err, syscall.EINVAL)
		return errors.New(str)
	}
	if n != 1 || oobn != len(rights) {
		str := fmt.Sprintf("Usock#WriteFD:WriteMsgUnix = %d, %d; want 1, %d\n", n, oobn, len(rights))
		return errors.New(str)
	}
	return nil
}
Example #10
0
func (s *OOBUnixConn) Write(buf []byte) (int, error) {
	var oob []byte
	s.m.Lock()
	fds := s.sendFDs
	s.sendFDs = nil
	s.m.Unlock()
	if len(fds) > 0 {
		oob = syscall.UnixRights(fds...)
	}
	n, oobn, err := s.WriteMsgUnix(buf, oob, nil)
	if err == nil && oobn != len(oob) {
		err = ErrOOBSendFailed
	}
	return n, err
}
Example #11
0
func SendFd(conn *net.UnixConn, file *os.File) error {
	rights := syscall.UnixRights(int(file.Fd()))
	dummy := []byte("x")
	n, oobn, err := conn.WriteMsgUnix(dummy, rights, nil)
	if err != nil {
		return fmt.Errorf("sendfd: err %v", err)
	}
	if n != len(dummy) {
		return fmt.Errorf("sendfd: short write %v", conn)
	}
	if oobn != len(rights) {
		return fmt.Errorf("sendfd: short oob write %v", conn)
	}
	return nil
}
Example #12
0
func writeData(conn *net.UnixConn, response *container_daemon.ResponseMessage) {
	data, _ := json.Marshal(response) // Ignore error

	args := make([]int, len(response.Files))
	for i, f := range response.Files {
		args[i] = int(f.Fd())
	}
	oobData := syscall.UnixRights(args...)

	conn.WriteMsgUnix(data, oobData, nil) // Ignore error

	// Close the files whose descriptors have been sent to the host to ensure that
	// a close on the host takes effect in a timely fashion.
	for _, file := range response.Files {
		file.Close() // Ignore error
	}
}
Example #13
0
// passFDChild is the child process used by TestPassFD.
func passFDChild() {
	defer os.Exit(0)

	// Look for our fd. It should be fd 3, but we work around an fd leak
	// bug here (http://golang.org/issue/2603) to let it be elsewhere.
	var uc *net.UnixConn
	for fd := uintptr(3); fd <= 10; fd++ {
		f := os.NewFile(fd, "unix-conn")
		var ok bool
		netc, _ := net.FileConn(f)
		uc, ok = netc.(*net.UnixConn)
		if ok {
			break
		}
	}
	if uc == nil {
		fmt.Println("failed to find unix fd")
		return
	}

	// Make a file f to send to our parent process on uc.
	// We make it in tempDir, which our parent will clean up.
	flag.Parse()
	tempDir := flag.Arg(0)
	f, err := ioutil.TempFile(tempDir, "")
	if err != nil {
		fmt.Printf("TempFile: %v", err)
		return
	}

	f.Write([]byte("Hello from child process!\n"))
	f.Seek(0, 0)

	rights := syscall.UnixRights(int(f.Fd()))
	dummyByte := []byte("x")
	n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
	if err != nil {
		fmt.Printf("WriteMsgUnix: %v", err)
		return
	}
	if n != 1 || oobn != len(rights) {
		fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
		return
	}
}
Example #14
0
func (u *Usock) WriteFD(fd int) error {
	u.Lock()
	defer u.Unlock()

	rights := syscall.UnixRights(fd)

	dummyByte := []byte{0}
	n, oobn, err := u.reader.Conn.WriteMsgUnix(dummyByte, rights, nil)
	if err != nil {
		str := fmt.Sprintf("Usock#WriteFD:WriteMsgUnix: %v / %v\n", err, syscall.EINVAL)
		return errors.New(str)
	}
	if n != 1 || oobn != len(rights) {
		str := fmt.Sprintf("Usock#WriteFD:WriteMsgUnix = %d, %d; want 1, %d\n", n, oobn, len(rights))
		return errors.New(str)
	}
	return nil
}
Example #15
0
func (c *Conn) WriteMessage(m *Message) (err error) {
	var payload []byte
	if m.p != nil {
		payload = m.p.Bytes()
	}
	if err = c.writeHeader(m.object, m.opcode, uint16(len(payload))); err != nil {
		return
	}
	if len(payload) == 0 {
		// message without payload wouldn't contain fds, so we can return here
		return nil
	}
	var oob []byte
	if len(m.fds) != 0 {
		oob = syscall.UnixRights(m.fds...)
	}
	_, _, err = c.c.WriteMsgUnix(payload, oob, nil)
	return
}
Example #16
0
func (conn *UnixConn) sendUnix(data []byte, fds ...int) error {
	header, err := makeHeader(data, fds)
	if err != nil {
		return err
	}

	// There is a bug in conn.WriteMsgUnix where it doesn't correctly return
	// the number of bytes writte (http://code.google.com/p/go/issues/detail?id=7645)
	// So, we can't rely on the return value from it. However, we must use it to
	// send the fds. In order to handle this we only write one byte using WriteMsgUnix
	// (when we have to), as that can only ever block or fully suceed. We then write
	// the rest with conn.Write()
	// The reader side should not rely on this though, as hopefully this gets fixed
	// in go later.
	written := 0
	if len(fds) != 0 {
		oob := syscall.UnixRights(fds...)
		wrote, _, err := conn.WriteMsgUnix(header[0:1], oob, nil)
		if err != nil {
			return err
		}
		written = written + wrote
	}

	for written < len(header) {
		wrote, err := conn.Write(header[written:])
		if err != nil {
			return err
		}
		written = written + wrote
	}

	written = 0
	for written < len(data) {
		wrote, err := conn.Write(data[written:])
		if err != nil {
			return err
		}
		written = written + wrote
	}

	return nil
}
Example #17
0
func sendmsg(msg *message) {
	size := len(msg.buf.Bytes())
	buf := new(bytes.Buffer)
	binary.Write(buf, binary.LittleEndian, msg.obj.Id())
	binary.Write(buf, binary.LittleEndian, msg.opcode)
	binary.Write(buf, binary.LittleEndian, int16(size+8))
	binary.Write(buf, binary.LittleEndian, msg.buf.Bytes())

	var cmsgbytes []byte
	if msg.fd != 0 {
		cmsgbytes = syscall.UnixRights(int(msg.fd))
	}
	_, _, err := conn.unixconn.WriteMsgUnix(buf.Bytes(), cmsgbytes, nil)
	if err != nil {
		fmt.Println("sendmsg", err)
		return
	}
	syscall.Close(int(msg.fd))
}
Example #18
0
// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
func TestUnixRightsRoundtrip(t *testing.T) {
	testCases := [...][][]int{
		{{42}},
		{{1, 2}},
		{{3, 4, 5}},
		{{}},
		{{1, 2}, {3, 4, 5}, {}, {7}},
	}
	for _, testCase := range testCases {
		b := []byte{}
		var n int
		for _, fds := range testCase {
			// Last assignment to n wins
			n = len(b) + syscall.CmsgLen(4*len(fds))
			b = append(b, syscall.UnixRights(fds...)...)
		}
		// Truncate b
		b = b[:n]

		scms, err := syscall.ParseSocketControlMessage(b)
		if err != nil {
			t.Fatalf("ParseSocketControlMessage: %v", err)
		}
		if len(scms) != len(testCase) {
			t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
		}
		for i, scm := range scms {
			gotFds, err := syscall.ParseUnixRights(&scm)
			if err != nil {
				t.Fatalf("ParseUnixRights: %v", err)
			}
			wantFds := testCase[i]
			if len(gotFds) != len(wantFds) {
				t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
			}
			for j, fd := range gotFds {
				if fd != wantFds[j] {
					t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
				}
			}
		}
	}
}
Example #19
0
func acceptConnection(listener net.Listener, stdoutR, stderrR, statusR *os.File) (net.Conn, error) {
	conn, err := listener.Accept()
	if err != nil {
		return nil, err
	}

	rights := syscall.UnixRights(
		int(stdoutR.Fd()),
		int(stderrR.Fd()),
		int(statusR.Fd()),
	)

	_, _, err = conn.(*net.UnixConn).WriteMsgUnix([]byte{}, rights, nil)
	if err != nil {
		return nil, err
	}

	return conn, nil
}
Example #20
0
func newNetworkAddSession(ctx *hypervisor.VmContext, qc *QemuContext, id string, fd uint64, device, mac string, index, addr int, result chan<- hypervisor.VmEvent) {
	busAddr := fmt.Sprintf("0x%x", addr)
	commands := make([]*QmpCommand, 3)
	scm := syscall.UnixRights(int(fd))
	glog.V(1).Infof("send net to qemu at %d", int(fd))
	commands[0] = &QmpCommand{
		Execute: "getfd",
		Arguments: map[string]interface{}{
			"fdname": "fd" + device,
		},
		Scm: scm,
	}
	commands[1] = &QmpCommand{
		Execute: "netdev_add",
		Arguments: map[string]interface{}{
			"type": "tap", "id": device, "fd": "fd" + device,
		},
	}
	commands[2] = &QmpCommand{
		Execute: "device_add",
		Arguments: map[string]interface{}{
			"netdev":         device,
			"driver":         "virtio-net-pci",
			"disable-modern": "off",
			"disable-legacy": "on",
			"bus":            "pci.0",
			"addr":           busAddr,
			"mac":            mac,
			"id":             device,
		},
	}

	qc.qmp <- &QmpSession{
		commands: commands,
		respond: defaultRespond(result, &hypervisor.NetDevInsertedEvent{
			Id:         id,
			Index:      index,
			DeviceName: device,
			Address:    addr,
		}),
	}
}
Example #21
0
File: fd.go Project: ftrvxmtrx/fd
// Put sends file descriptors to Unix domain socket.
//
// Please note that the number of descriptors in one message is limited
// and is rather small.
// Use conn.File() to get a file if you want to put a network connection.
func Put(via *net.UnixConn, files ...*os.File) error {
	if len(files) == 0 {
		return nil
	}

	viaf, err := via.File()
	if err != nil {
		return err
	}
	socket := int(viaf.Fd())
	defer viaf.Close()

	fds := make([]int, len(files))
	for i := range files {
		fds[i] = int(files[i].Fd())
	}

	rights := syscall.UnixRights(fds...)
	return syscall.Sendmsg(socket, nil, rights, nil, 0)
}
Example #22
0
func newNetworkAddSession(qc *QemuContext, fd uint64, device, mac string, index, addr int) {
	busAddr := fmt.Sprintf("0x%x", addr)
	commands := make([]*QmpCommand, 3)
	scm := syscall.UnixRights(int(fd))
	glog.V(1).Infof("send net to qemu at %d", int(fd))
	commands[0] = &QmpCommand{
		Execute: "getfd",
		Arguments: map[string]interface{}{
			"fdname": "fd" + device,
		},
		Scm: scm,
	}
	commands[1] = &QmpCommand{
		Execute: "netdev_add",
		Arguments: map[string]interface{}{
			"type": "tap", "id": device, "fd": "fd" + device,
		},
	}
	commands[2] = &QmpCommand{
		Execute: "device_add",
		Arguments: map[string]interface{}{
			"driver": "virtio-net-pci",
			"netdev": device,
			"mac":    mac,
			"bus":    "pci.0",
			"addr":   busAddr,
			"id":     device,
		},
	}

	qc.qmp <- &QmpSession{
		commands: commands,
		callback: &hypervisor.NetDevInsertedEvent{
			Index:      index,
			DeviceName: device,
			Address:    addr,
		},
	}
}
Example #23
0
// Send a message to the local systemd journal. vars is a map of journald
// fields to values.  Fields must be composed of uppercase letters, numbers,
// and underscores, but must not start with an underscore. Within these
// restrictions, any arbitrary field name may be used.  Some names have special
// significance: see the journalctl documentation
// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
// for more details.  vars may be nil.
func Send(message string, priority Priority, vars map[string]string) error {
	if conn == nil {
		return journalError("could not connect to journald socket")
	}

	data := new(bytes.Buffer)
	appendVariable(data, "PRIORITY", strconv.Itoa(int(priority)))
	appendVariable(data, "MESSAGE", message)
	for k, v := range vars {
		appendVariable(data, k, v)
	}

	_, err := io.Copy(conn, data)
	if err != nil && isSocketSpaceError(err) {
		file, err := tempFd()
		if err != nil {
			return journalError(err.Error())
		}
		defer file.Close()
		_, err = io.Copy(file, data)
		if err != nil {
			return journalError(err.Error())
		}

		rights := syscall.UnixRights(int(file.Fd()))

		/* this connection should always be a UnixConn, but better safe than sorry */
		unixConn, ok := conn.(*net.UnixConn)
		if !ok {
			return journalError("can't send file through non-Unix connection")
		}
		unixConn.WriteMsgUnix([]byte{}, rights, nil)
	} else if err != nil {
		return journalError(err.Error())
	}
	return nil
}
Example #24
0
func sendUnix(conn *net.UnixConn, data []byte, fds ...int) error {
	_, _, err := conn.WriteMsgUnix(data, syscall.UnixRights(fds...), nil)
	return err
}
Example #25
0
func sendrequest(obj Object, req string, args ...interface{}) {
	if conn.alive != true {
		return
	}
	data := new(bytes.Buffer)
	dbg := new(bytes.Buffer)
	size := 8
	fd := uintptr(0)
	signature := signatures[req]
	opcode := signature.opcode
	sig := signature.signature
	for i, arg := range args {
		switch sig[i] {
		case 'i', 'f':
			size += 4
			binary.Write(data, binary.LittleEndian, arg.(int32))
			fmt.Fprintf(dbg, "%d ", arg)
		case 'u':
			size += 4
			binary.Write(data, binary.LittleEndian, arg.(uint32))
			fmt.Fprintf(dbg, "%d ", arg)
		case 'h':
			fd, _, _ = syscall.Syscall(syscall.SYS_FCNTL, arg.(uintptr), syscall.F_DUPFD_CLOEXEC, 0)
		case 'o':
			size += 4
			binary.Write(data, binary.LittleEndian, arg.(Object).Id())
			fmt.Fprintf(dbg, "%d ", arg.(Object).Id())
		case 'n':
			size += 4
			nobj := arg.(Object)
			appendObject(nobj)
			binary.Write(data, binary.LittleEndian, nobj.Id())
			fmt.Fprintf(dbg, "new_id %d ", nobj.Id())
		case 's':
			// First get padding
			str := arg.(string)
			pad := 4 - (len(str) % 4)
			binary.Write(data, binary.LittleEndian, int32(len(str)+pad))
			binary.Write(data, binary.LittleEndian, []byte(str))
			for i := 0; i < pad; i++ {
				binary.Write(data, binary.LittleEndian, []byte{0})
			}
			size += len(str) + pad + 4
			fmt.Fprintf(dbg, "%s ", str)
		}
	}

	fmt.Printf(" -> %s@%d ( %s)\n", req, obj.Id(), dbg)

	// Send message
	buf := new(bytes.Buffer)
	binary.Write(buf, binary.LittleEndian, obj.Id())
	binary.Write(buf, binary.LittleEndian, opcode)
	binary.Write(buf, binary.LittleEndian, int16(size))
	binary.Write(buf, binary.LittleEndian, data.Bytes())

	var cmsgbytes []byte
	if fd != 0 {
		cmsgbytes = syscall.UnixRights(int(fd))
	}
	_, _, err := conn.unixconn.WriteMsgUnix(buf.Bytes(), cmsgbytes, nil)
	if err != nil {
		fmt.Println("sendrequest", err)
		os.Exit(1)
		return
	}
	syscall.Close(int(fd))
}
Example #26
0
File: ipc.go Project: drptbl/oz
func (mc *MsgConn) sendWithFds(data []byte, fds []int) error {
	oob := syscall.UnixRights(fds...)
	_, _, err := mc.conn.WriteMsgUnix(data, oob, nil)
	return err
}
Example #27
0
		var (
			stdoutR, stderrR, statusR *os.File
		)

		stdoutR, stdoutW, err = os.Pipe()
		Expect(err).ToNot(HaveOccurred())
		stderrR, stderrW, err = os.Pipe()
		Expect(err).ToNot(HaveOccurred())
		statusR, statusW, err = os.Pipe()
		Expect(err).ToNot(HaveOccurred())

		fakeServer.SetConnectionHandler(func(conn net.Conn) {
			rights := syscall.UnixRights(
				int(stdoutR.Fd()),
				int(stderrR.Fd()),
				int(statusR.Fd()),
			)

			conn.(*net.UnixConn).WriteMsgUnix([]byte{}, rights, nil)
		})
	})

	JustBeforeEach(func() {
		go fakeServer.Serve()
	})

	AfterEach(func() {
		Expect(fakeServer.Stop()).To(Succeed())

		Expect(os.RemoveAll(path.Base(unixSockerPath))).To(Succeed())