This allows running big endian and little endian guest side by side using cut&paste between them. There is some general design idea that swapping should come as cloce to virtio_read/virtio_write as possible. In particular, the protocol between vdagent and vdagentd is guest-specific and in native endian. With muliple layers of headers this is a bit tricky. A few message types have to be swapped fully before passing through vdagentd. Signed-off-by: Michal Suchanek <msuchanek@xxxxxxx> --- src/vdagentd/uinput.c | 4 +++ src/vdagentd/vdagentd.c | 68 ++++++++++++++++++++++++++++++++++------------ src/vdagentd/virtio-port.c | 35 +++++++++++++++--------- 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/vdagentd/uinput.c b/src/vdagentd/uinput.c index e2966c4..21292cb 100644 --- a/src/vdagentd/uinput.c +++ b/src/vdagentd/uinput.c @@ -200,6 +200,10 @@ void vdagentd_uinput_do_mouse(struct vdagentd_uinput **uinputp, }; int i, down; + mouse->x = le32toh(mouse->x); + mouse->y = le32toh(mouse->y); + mouse->buttons = le32toh(mouse->buttons); + if (*uinputp) { if (mouse->display_id >= uinput->screen_count) { syslog(LOG_WARNING, "mouse event for unknown monitor (%d >= %d)", diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c index a1faf23..f91434d 100644 --- a/src/vdagentd/vdagentd.c +++ b/src/vdagentd/vdagentd.c @@ -83,7 +83,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, uint32_t request) { VDAgentAnnounceCapabilities *caps; - uint32_t size; + uint32_t size, i; size = sizeof(*caps) + VD_AGENT_CAPS_BYTES; caps = calloc(1, size); @@ -92,7 +92,7 @@ static void send_capabilities(struct vdagent_virtio_port *vport, return; } - caps->request = request; + caps->request = htole32(request); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MOUSE_STATE); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MONITORS_CONFIG); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_REPLY); @@ -102,6 +102,8 @@ static void send_capabilities(struct vdagent_virtio_port *vport, VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); + for (i = 0; i < VD_AGENT_CAPS_SIZE; i++) + caps->caps[i] = le32toh(caps->caps[i]); vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, VD_AGENT_ANNOUNCE_CAPABILITIES, 0, @@ -122,7 +124,10 @@ static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, VDAgentMessage *message_header, VDAgentMonitorsConfig *new_monitors) { VDAgentReply reply; - uint32_t size; + uint32_t size, i; + + new_monitors->num_of_monitors = le32toh(new_monitors->num_of_monitors); + new_monitors->flags = le32toh(new_monitors->flags); /* Store monitor config to send to agents when they connect */ size = sizeof(VDAgentMonitorsConfig) + @@ -132,6 +137,14 @@ static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, return; } + for (i = 0; i < new_monitors->num_of_monitors; i++) { + new_monitors->monitors[i].height = le32toh(new_monitors->monitors[i].height); + new_monitors->monitors[i].width = le32toh(new_monitors->monitors[i].width); + new_monitors->monitors[i].depth = le32toh(new_monitors->monitors[i].depth); + new_monitors->monitors[i].x = le32toh(new_monitors->monitors[i].x); + new_monitors->monitors[i].y = le32toh(new_monitors->monitors[i].y); + } + vdagentd_write_xorg_conf(new_monitors); if (!mon_config || @@ -151,8 +164,8 @@ static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, (uint8_t *)mon_config, size); /* Acknowledge reception of monitors config to spice server / client */ - reply.type = VD_AGENT_MONITORS_CONFIG; - reply.error = VD_AGENT_SUCCESS; + reply.type = htole32(VD_AGENT_MONITORS_CONFIG); + reply.error = htole32(VD_AGENT_SUCCESS); vdagent_virtio_port_write(vport, port_nr, VD_AGENT_REPLY, 0, (uint8_t *)&reply, sizeof(reply)); } @@ -161,11 +174,15 @@ static void do_client_volume_sync(struct vdagent_virtio_port *vport, int port_nr VDAgentMessage *message_header, VDAgentAudioVolumeSync *avs) { + int i; if (active_session_conn == NULL) { syslog(LOG_DEBUG, "No active session - Can't volume-sync"); return; } + for (i = 0; i < avs->nchannels; i++) + avs->volume[i] = le16toh(avs->volume[i]); + udscs_write(active_session_conn, VDAGENTD_AUDIO_VOLUME_SYNC, 0, 0, (uint8_t *)avs, message_header->size); } @@ -174,7 +191,7 @@ static void do_client_capabilities(struct vdagent_virtio_port *vport, VDAgentMessage *message_header, VDAgentAnnounceCapabilities *caps) { - int new_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message_header->size); + int i, new_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message_header->size); if (capabilities_size != new_size) { capabilities_size = new_size; @@ -186,7 +203,8 @@ static void do_client_capabilities(struct vdagent_virtio_port *vport, return; } } - memcpy(capabilities, caps->caps, capabilities_size * sizeof(uint32_t)); + for (i = 0; i < capabilities_size; i++) + capabilities[i] = le32toh(caps->caps[i]); if (caps->request) { /* Report the previous client has disconneced. */ do_client_disconnect(); @@ -225,7 +243,7 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, case VD_AGENT_CLIPBOARD_REQUEST: { VDAgentClipboardRequest *req = (VDAgentClipboardRequest *)data; msg_type = VDAGENTD_CLIPBOARD_REQUEST; - data_type = req->type; + data_type = le32toh(req->type); data = NULL; size = 0; break; @@ -233,7 +251,7 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, case VD_AGENT_CLIPBOARD: { VDAgentClipboard *clipboard = (VDAgentClipboard *)data; msg_type = VDAGENTD_CLIPBOARD_DATA; - data_type = clipboard->type; + data_type = le32toh(clipboard->type); size = size - sizeof(VDAgentClipboard); data = clipboard->data; break; @@ -255,8 +273,8 @@ static void send_file_xfer_status(struct vdagent_virtio_port *vport, const char *msg, uint32_t id, uint32_t xfer_status) { VDAgentFileXferStatusMessage status = { - .id = id, - .result = xfer_status, + .id = htole32(id), + .result = htole32(xfer_status), }; syslog(LOG_WARNING, msg, id); if (vport) @@ -275,6 +293,7 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, switch (message_header->type) { case VD_AGENT_FILE_XFER_START: { VDAgentFileXferStartMessage *s = (VDAgentFileXferStartMessage *)data; + s->id = le32toh(s->id); if (!active_session_conn) { send_file_xfer_status(vport, "Could not find an agent connnection belonging to the " @@ -295,12 +314,16 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport, } case VD_AGENT_FILE_XFER_STATUS: { VDAgentFileXferStatusMessage *s = (VDAgentFileXferStatusMessage *)data; + s->id = le32toh(s->id); + s->result = le64toh(s->result); msg_type = VDAGENTD_FILE_XFER_STATUS; id = s->id; break; } case VD_AGENT_FILE_XFER_DATA: { VDAgentFileXferDataMessage *d = (VDAgentFileXferDataMessage *)data; + d->id = le32toh(d->id); + d->size = le64toh(d->size); msg_type = VDAGENTD_FILE_XFER_DATA; id = d->id; break; @@ -399,15 +422,18 @@ static int virtio_port_read_complete( if (message_header->size != sizeof(VDAgentMaxClipboard)) goto size_error; VDAgentMaxClipboard *msg = (VDAgentMaxClipboard *)data; - syslog(LOG_DEBUG, "Set max clipboard: %d", msg->max); - max_clipboard = msg->max; + syslog(LOG_DEBUG, "Set max clipboard: %d", le32toh(msg->max)); + max_clipboard = le32toh(msg->max); break; case VD_AGENT_AUDIO_VOLUME_SYNC: if (message_header->size < sizeof(VDAgentAudioVolumeSync)) goto size_error; + VDAgentAudioVolumeSync *vdata = (VDAgentAudioVolumeSync *)data; + if (message_header->size < sizeof(VDAgentAudioVolumeSync) + + vdata->nchannels * sizeof(vdata->volume[0])) + goto size_error; - do_client_volume_sync(vport, port_nr, message_header, - (VDAgentAudioVolumeSync *)data); + do_client_volume_sync(vport, port_nr, message_header, vdata); break; default: syslog(LOG_WARNING, "unknown message type %d, ignoring", @@ -444,6 +470,7 @@ static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, vdagent_virtio_port_write_append(virtio_port, sel, 4); } if (data_type != -1) { + data_type = htole32(data_type); vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4); } @@ -452,10 +479,11 @@ static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, /* vdagentd <-> vdagent communication handling */ static int do_agent_clipboard(struct udscs_connection *conn, - struct udscs_message_header *header, const uint8_t *data) + struct udscs_message_header *header, uint8_t *data) { uint8_t selection = header->arg1; uint32_t msg_type = 0, data_type = -1, size = header->size; + int i; if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) @@ -483,6 +511,10 @@ static int do_agent_clipboard(struct udscs_connection *conn, switch (header->type) { case VDAGENTD_CLIPBOARD_GRAB: msg_type = VD_AGENT_CLIPBOARD_GRAB; + if (size % sizeof(uint32_t)) + syslog(LOG_ERR, "Clipboard grab imessage size not multiple of %zu", sizeof(uint32_t)); + for(i = 0; i < size / sizeof(uint32_t); i++) + ((uint32_t*)data)[i] = htole32(((uint32_t*)data)[i]); agent_owns_clipboard[selection] = 1; break; case VDAGENTD_CLIPBOARD_REQUEST: @@ -763,8 +795,8 @@ static void agent_read_complete(struct udscs_connection **connp, break; case VDAGENTD_FILE_XFER_STATUS:{ VDAgentFileXferStatusMessage status; - status.id = header->arg1; - status.result = header->arg2; + status.id = htole32(header->arg1); + status.result = htole32(header->arg2); vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT, VD_AGENT_FILE_XFER_STATUS, 0, (uint8_t *)&status, sizeof(status)); diff --git a/src/vdagentd/virtio-port.c b/src/vdagentd/virtio-port.c index cedda4d..ac4d805 100644 --- a/src/vdagentd/virtio-port.c +++ b/src/vdagentd/virtio-port.c @@ -216,16 +216,16 @@ int vdagent_virtio_port_write_start( return -1; } - chunk_header.port = port_nr; - chunk_header.size = sizeof(message_header) + data_size; + chunk_header.port = htole32(port_nr); + chunk_header.size = htole32(sizeof(message_header) + data_size); memcpy(new_wbuf->buf + new_wbuf->write_pos, &chunk_header, sizeof(chunk_header)); new_wbuf->write_pos += sizeof(chunk_header); - message_header.protocol = VD_AGENT_PROTOCOL; - message_header.type = message_type; - message_header.opaque = message_opaque; - message_header.size = data_size; + message_header.protocol = htole32(VD_AGENT_PROTOCOL); + message_header.type = htole32(message_type); + message_header.opaque = htole64(message_opaque); + message_header.size = htole32(data_size); memcpy(new_wbuf->buf + new_wbuf->write_pos, &message_header, sizeof(message_header)); new_wbuf->write_pos += sizeof(message_header); @@ -309,13 +309,20 @@ static void vdagent_virtio_port_do_chunk(struct vdagent_virtio_port **vportp) memcpy((uint8_t *)&port->message_header + port->message_header_read, vport->chunk_data, read); port->message_header_read += read; - if (port->message_header_read == sizeof(port->message_header) && - port->message_header.size) { - port->message_data = malloc(port->message_header.size); - if (!port->message_data) { - syslog(LOG_ERR, "out of memory, disconnecting virtio"); - vdagent_virtio_port_destroy(vportp); - return; + if (port->message_header_read == sizeof(port->message_header)) { + + port->message_header.protocol = le32toh(port->message_header.protocol); + port->message_header.type = le32toh(port->message_header.type); + port->message_header.opaque = le64toh(port->message_header.opaque); + port->message_header.size = le32toh(port->message_header.size); + + if (port->message_header.size) { + port->message_data = malloc(port->message_header.size); + if (!port->message_data) { + syslog(LOG_ERR, "out of memory, disconnecting virtio"); + vdagent_virtio_port_destroy(vportp); + return; + } } } pos = read; @@ -420,6 +427,8 @@ static void vdagent_virtio_port_do_read(struct vdagent_virtio_port **vportp) if (vport->chunk_header_read < sizeof(vport->chunk_header)) { vport->chunk_header_read += n; if (vport->chunk_header_read == sizeof(vport->chunk_header)) { + vport->chunk_header.size = le32toh(vport->chunk_header.size); + vport->chunk_header.port = le32toh(vport->chunk_header.port); if (vport->chunk_header.size > VD_AGENT_MAX_DATA_SIZE) { syslog(LOG_ERR, "chunk size %u too large", vport->chunk_header.size); -- 2.10.2 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel