From nobody Thu Dec 18 23:01:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1678293617; cv=none; d=zohomail.com; s=zohoarc; b=CKdHUAYLCt77hJPzEtQ8xqty4aWy8FGzlYpWfzwtLSlNA/r9QQEecR8/Z/z0bA6qNBNnQgma8qLt7zc9YwUyJE6Llhocv8vrae7uQhIPRHY0D6EZUHS+soO2Nz3JUMYbByV4LU2IMw60zkrR3RB/q3naHrTEmAb2X+ZaZam/W9s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1678293617; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ukH7zulqyjAoXtZGiPCcY6GA2KrooYgc3RMooEF2G0E=; b=TilDPEFq7MBYl8+Iuc2b3Y8g+cBUbpDsu62fM6rS84S+wzfz8mVDGKRbqDtMpfAliW9LtvrDUprExMMUtDygDEWi20+fOPT4cn0OFl7AX2GbGtFXZOgw8IXDGsI5APvCTYsLfFrdJRmrqHu/VKNTsNbBIQ0yPgwgkbuYV8t1Nms= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1678293617848369.5905633779055; Wed, 8 Mar 2023 08:40:17 -0800 (PST) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-637-_APZySvaN1meElPzQeJzkw-1; Wed, 08 Mar 2023 11:39:40 -0500 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6D7CC886461; Wed, 8 Mar 2023 16:39:27 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 52236492B15; Wed, 8 Mar 2023 16:39:27 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 9819C19472E2; Wed, 8 Mar 2023 16:39:23 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 735E019472C6 for ; Wed, 8 Mar 2023 16:39:20 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 589B11121330; Wed, 8 Mar 2023 16:39:20 +0000 (UTC) Received: from virtlab420.virt.lab.eng.bos.redhat.com (virtlab420.virt.lab.eng.bos.redhat.com [10.19.152.148]) by smtp.corp.redhat.com (Postfix) with ESMTP id 39B5F1121314; Wed, 8 Mar 2023 16:39:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678293616; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ukH7zulqyjAoXtZGiPCcY6GA2KrooYgc3RMooEF2G0E=; b=dYfmazdUp71BdHovmahT1CAtFChHcZyrG4RwBaWPwWpSLdauwV4H/+U/WvtIlAKEqTw5da 42nyjFFconU9l9yG3nfUrLVhtwoiQ5wYIRyz/UAzbT8QjZFSzzolTujjwcQcvUw1fyOB6v dX0zOkGE70vNPXmUCWLb1uxZ5xrMjKI= X-MC-Unique: _APZySvaN1meElPzQeJzkw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [PATCH 16/16] rpc: add helpers for XDR type serialization Date: Wed, 8 Mar 2023 11:39:13 -0500 Message-Id: <20230308163913.338952-17-berrange@redhat.com> In-Reply-To: <20230308163913.338952-1-berrange@redhat.com> References: <20230308163913.338952-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1678293618951100003 As preparation for eliminating the use of the XDR library, introduce helpers for (de)serializing XDR types from/to the virNetMessage object. In contrast to the XDR APIs, when encoding data our helpers can dynamically resize the virNetMessage buffer. Our decode helpers also exhibit delayed error reporting, so that callers can deserialize a bunch of data and check for errors once at the end. Signed-off-by: Daniel P. Berrang=C3=A9 --- src/rpc/virnetmessage.c | 704 ++++++++++++++++++++++++++++++++++++++++ src/rpc/virnetmessage.h | 88 +++++ 2 files changed, 792 insertions(+) diff --git a/src/rpc/virnetmessage.c b/src/rpc/virnetmessage.c index c9698fb263..df9a1aea71 100644 --- a/src/rpc/virnetmessage.c +++ b/src/rpc/virnetmessage.c @@ -593,3 +593,707 @@ int virNetMessageAddFD(virNetMessage *msg, VIR_FORCE_CLOSE(newfd); return -1; } + +static void virNetMessageEncodePrealloc(virNetMessage *msg, size_t len) +{ + if ((msg->bufferLength - msg->bufferOffset) > len) + return; + + /* + * Over allocate by 64kb, since we'll almost certainly + * have more fields written soon + */ + msg->bufferLength +=3D len + (1024 * 64); + msg->buffer =3D g_realloc_n(msg->buffer, 1, msg->bufferLength); +} + +static bool virNetMessageDecodePending(virNetMessage *msg, size_t len) +{ + if ((msg->bufferLength - msg->bufferOffset) < len) { + msg->decodeErrno =3D ENOSPC; + } + + /* Always return msg->decodeErrno, even if we didn't set it, + * because we allow multiple decode calls to be run without + * the caller checking for errors + */ + return msg->decodeErrno =3D=3D 0; +} + +#define VIR_NET_MESSAGE_ENCODE_UINT32 \ + uint32_t p =3D htonl((uint32_t)v); \ + virNetMessageEncodePrealloc(msg, sizeof(uint32_t)); \ + memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p) + +#define VIR_NET_MESSAGE_DECODE_UINT32(t) \ + uint32_t p; \ + if (!virNetMessageDecodePending(msg, sizeof(uint32_t))) \ + return; \ + memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *v =3D (t)ntohl((uint32_t)p); + +#define VIR_NET_MESSAGE_ENCODE_UINT64 \ + uint32_t p[2] =3D { \ + htonl((uint32_t)(((uint64_t)v >> 32) & 0xffffffff)), \ + htonl((uint32_t)((uint64_t)v & 0xffffffff)), \ + }; \ + virNetMessageEncodePrealloc(msg, sizeof(uint64_t)); \ + memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p) + +#define VIR_NET_MESSAGE_DECODE_UINT64(t) \ + uint32_t p[2]; \ + if (!virNetMessageDecodePending(msg, sizeof(uint64_t))) \ + return; \ + memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *v =3D (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1])); + + +void virNetMessageEncodeInt8(virNetMessage *msg, int8_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeInt8(virNetMessage *msg, int8_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(int8_t); +} + +void virNetMessageEncodeUInt8(virNetMessage *msg, uint8_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeUInt8(virNetMessage *msg, uint8_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(uint8_t); +} + +void virNetMessageEncodeInt16(virNetMessage *msg, int16_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeInt16(virNetMessage *msg, int16_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(int16_t); +} + +void virNetMessageEncodeUInt16(virNetMessage *msg, uint16_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeUInt16(virNetMessage *msg, uint16_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(uint16_t); +} + +void virNetMessageEncodeInt32(virNetMessage *msg, int32_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeInt32(virNetMessage *msg, int32_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(int32_t); +} + +void virNetMessageEncodeUInt32(virNetMessage *msg, uint32_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeUInt32(virNetMessage *msg, uint32_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(uint32_t); +} + +void virNetMessageEncodeInt64(virNetMessage *msg, int64_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT64; +} + +void virNetMessageDecodeInt64(virNetMessage *msg, int64_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT64(int64_t); +} + +void virNetMessageEncodeUInt64(virNetMessage *msg, uint64_t v) +{ + VIR_NET_MESSAGE_ENCODE_UINT64; +} + +void virNetMessageDecodeUInt64(virNetMessage *msg, uint64_t *v) +{ + VIR_NET_MESSAGE_DECODE_UINT64(uint64_t); +} + +G_STATIC_ASSERT(sizeof(float) =3D=3D sizeof(uint32_t)); +void virNetMessageEncodeFloat(virNetMessage *msg, float v) +{ + VIR_NET_MESSAGE_ENCODE_UINT32; +} + +void virNetMessageDecodeFloat(virNetMessage *msg, float *v) +{ + VIR_NET_MESSAGE_DECODE_UINT32(float); +} + +G_STATIC_ASSERT(sizeof(double) =3D=3D sizeof(uint64_t)); +void virNetMessageEncodeDouble(virNetMessage *msg, double v) +{ + /* XXXX check I'm doing byte order right here */ + VIR_NET_MESSAGE_ENCODE_UINT64; +} + +void virNetMessageDecodeDouble(virNetMessage *msg, double *v) +{ + /* XXXX check I'm doing byte order right here */ + VIR_NET_MESSAGE_DECODE_UINT64(double); +} + +void virNetMessageEncodeBool(virNetMessage *msg, bool v) +{ + uint32_t p =3D htonl(v ? 1 : 0); + virNetMessageEncodePrealloc(msg, sizeof(p)); + memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); + msg->bufferOffset +=3D sizeof(p); +} + +void virNetMessageDecodeBool(virNetMessage *msg, bool *v) +{ + uint32_t p; + if (!virNetMessageDecodePending(msg, sizeof(uint32_t))) + return; + memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); + msg->bufferOffset +=3D sizeof(p); + *v =3D ntohl((uint32_t)p) =3D=3D 1 ? true : false; +} + +#define VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32 \ + do { \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert((G_MAXSIZE / sizeof(uint32_t)) > len); \ + virNetMessageEncodePrealloc(msg, sizeof(uint32_t) * len); \ + while (len) { \ + uint32_t p =3D htonl((uint32_t)*v); \ + memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + v++; \ + len--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(t) \ + do { \ + t *vp; \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert((G_MAXSIZE / sizeof(uint32_t)) > len); \ + if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * len)) \ + return; \ + *v =3D vp =3D g_new0(t, len); \ + while (len) { \ + uint32_t p; \ + memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *vp =3D (t)ntohl(p); \ + vp++; \ + len--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64 \ + do { \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert((G_MAXSIZE / sizeof(uint64_t)) > len); \ + virNetMessageEncodePrealloc(msg, sizeof(uint32_t) * len); \ + while (len) { \ + uint32_t p[2] =3D { \ + htonl((uint32_t)(((uint64_t)*v >> 32) & 0xffffffff)), \ + htonl((uint32_t)((uint64_t)*v & 0xffffffff)), \ + }; \ + memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + v++; \ + len--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(t) \ + do { \ + t *vp; \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert((G_MAXSIZE / sizeof(uint64_t)) > len); \ + if (!virNetMessageDecodePending(msg, sizeof(uint64_t) * len)) \ + return; \ + *v =3D vp =3D g_new0(t, len); \ + while (len) { \ + uint32_t p[2]; \ + memcpy(p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *vp =3D (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1])); \ + vp++; \ + len--; \ + } \ + } while (0) + +void virNetMessageEncodeInt8FixedArray(virNetMessage *msg, int8_t *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeInt8FixedArray(virNetMessage *msg, int8_t **v, siz= e_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int8_t); +} + +void virNetMessageEncodeUInt8FixedArray(virNetMessage *msg, uint8_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt8FixedArray(virNetMessage *msg, uint8_t **v, s= ize_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint8_t); +} + +void virNetMessageEncodeInt16FixedArray(virNetMessage *msg, int16_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeInt16FixedArray(virNetMessage *msg, int16_t **v, s= ize_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int16_t); +} + +void virNetMessageEncodeUInt16FixedArray(virNetMessage *msg, uint16_t *v, = size_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt16FixedArray(virNetMessage *msg, uint16_t **v,= size_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint16_t); +} + +void virNetMessageEncodeInt32FixedArray(virNetMessage *msg, int32_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeInt32FixedArray(virNetMessage *msg, int32_t **v, s= ize_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(int32_t); +} + +void virNetMessageEncodeUInt32FixedArray(virNetMessage *msg, uint32_t *v, = size_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt32FixedArray(virNetMessage *msg, uint32_t **v,= size_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(uint32_t); +} + +void virNetMessageEncodeInt64FixedArray(virNetMessage *msg, int64_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64; +} + +void virNetMessageDecodeInt64FixedArray(virNetMessage *msg, int64_t **v, s= ize_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(int64_t); +} + +void virNetMessageEncodeUInt64FixedArray(virNetMessage *msg, uint64_t *v, = size_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64; +} + +void virNetMessageDecodeUInt64FixedArray(virNetMessage *msg, uint64_t **v,= size_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(uint64_t); +} + +void virNetMessageEncodeFloatFixedArray(virNetMessage *msg, float *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT32; +} + +void virNetMessageDecodeFloatFixedArray(virNetMessage *msg, float **v, siz= e_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT32(float); +} + +void virNetMessageEncodeDoubleFixedArray(virNetMessage *msg, double *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_FIXED_ARRAY_UINT64; +} + +void virNetMessageDecodeDoubleFixedArray(virNetMessage *msg, double **v, s= ize_t len) +{ + VIR_NET_MESSAGE_DECODE_FIXED_ARRAY_UINT64(double); +} + +#define VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32 \ + do { \ + uint32_t lenp =3D htonl(len); \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert(((G_MAXSIZE - sizeof(uint32_t))/ sizeof(uint32_t)) > len)= ; \ + virNetMessageEncodePrealloc(msg, sizeof(uint32_t) + (sizeof(uint32= _t) * len)); \ + memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); \ + msg->bufferOffset +=3D sizeof(lenp); \ + while (len) { \ + uint32_t p =3D htonl((uint32_t)*v); \ + memcpy(msg->buffer + msg->bufferOffset, &p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + v++; \ + len--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(t) \ + do { \ + t *vp; \ + uint32_t lentmp; \ + virNetMessageDecodeUInt32(msg, &lentmp); \ + if (msg->decodeErrno !=3D 0) { \ + return; \ + } \ + if (lentmp > maxlen) { \ + msg->decodeErrno =3D EFBIG; \ + return; \ + } \ + g_assert(lentmp < (G_MAXUINT32 - 1)); \ + /* g_assert((G_MAXSIZE / sizeof(uint32_t)) > lentmp);*/ \ + if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * lentmp)) \ + return; \ + *v =3D vp =3D g_new0(t, lentmp); \ + *len =3D lentmp; \ + while (lentmp) { \ + uint32_t p; \ + memcpy(&p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *vp =3D (t)ntohl(p); \ + vp++; \ + lentmp--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64 \ + do { \ + uint32_t lenp =3D htonl(len); \ + g_assert(len < (G_MAXUINT32 - 1)); \ + g_assert(((G_MAXSIZE - sizeof(uint32_t))/ sizeof(uint64_t)) > len)= ; \ + virNetMessageEncodePrealloc(msg, sizeof(uint32_t) + (sizeof(uint64= _t) * len)); \ + memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); \ + msg->bufferOffset +=3D sizeof(lenp); \ + while (len) { \ + uint32_t p[2] =3D { \ + htonl((uint32_t)(((uint64_t)*v >> 32) & 0xffffffff)), \ + htonl((uint32_t)((uint64_t)*v & 0xffffffff)), \ + }; \ + memcpy(msg->buffer + msg->bufferOffset, p, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + v++; \ + len--; \ + } \ + } while (0) + +#define VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(t) \ + do { \ + t *vp; \ + uint32_t lentmp; \ + virNetMessageDecodeUInt32(msg, &lentmp); \ + if (msg->decodeErrno !=3D 0) { \ + return; \ + } \ + if (lentmp > maxlen) { \ + msg->decodeErrno =3D EFBIG; \ + return; \ + } \ + g_assert(lentmp < (G_MAXUINT32 - 1)); \ + /* g_assert((G_MAXSIZE / sizeof(uint32_t)) > lentmp);*/ \ + if (!virNetMessageDecodePending(msg, sizeof(uint32_t) * lentmp)) \ + return; \ + *v =3D vp =3D g_new0(t, lentmp); \ + *len =3D lentmp; \ + while (lentmp) { \ + uint32_t p[2]; \ + memcpy(p, msg->buffer + msg->bufferOffset, sizeof(p)); \ + msg->bufferOffset +=3D sizeof(p); \ + *vp =3D (t)((((uint64_t)ntohl(p[0])) << 32) + ntohl(p[1])); \ + vp++; \ + lentmp--; \ + } \ + } while (0) + + +void virNetMessageEncodeInt8DynArray(virNetMessage *msg, int8_t *v, size_t= len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeInt8DynArray(virNetMessage *msg, size_t maxlen, in= t8_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int8_t); +} + +void virNetMessageEncodeUInt8DynArray(virNetMessage *msg, uint8_t *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt8DynArray(virNetMessage *msg, size_t maxlen, u= int8_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint8_t); +} + +void virNetMessageEncodeInt16DynArray(virNetMessage *msg, int16_t *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeInt16DynArray(virNetMessage *msg, size_t maxlen, i= nt16_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int16_t); +} + +void virNetMessageEncodeUInt16DynArray(virNetMessage *msg, uint16_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt16DynArray(virNetMessage *msg, size_t maxlen, = uint16_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint16_t); +} + +void virNetMessageEncodeInt32DynArray(virNetMessage *msg, int32_t *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeInt32DynArray(virNetMessage *msg, size_t maxlen, i= nt32_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(int32_t); +} + +void virNetMessageEncodeUInt32DynArray(virNetMessage *msg, uint32_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeUInt32DynArray(virNetMessage *msg, size_t maxlen, = uint32_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(uint32_t); +} + +void virNetMessageEncodeInt64DynArray(virNetMessage *msg, int64_t *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64; +} + +void virNetMessageDecodeInt64DynArray(virNetMessage *msg, size_t maxlen, i= nt64_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(int64_t); +} + +void virNetMessageEncodeUInt64DynArray(virNetMessage *msg, uint64_t *v, si= ze_t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64; +} + +void virNetMessageDecodeUInt64DynArray(virNetMessage *msg, size_t maxlen, = uint64_t **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(uint64_t); +} + +void virNetMessageEncodeFloatDynArray(virNetMessage *msg, float *v, size_t= len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT32; +} + +void virNetMessageDecodeFloatDynArray(virNetMessage *msg, size_t maxlen, f= loat **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT32(float); +} + +void virNetMessageEncodeDoubleDynArray(virNetMessage *msg, double *v, size= _t len) +{ + VIR_NET_MESSAGE_ENCODE_DYN_ARRAY_UINT64; +} + +void virNetMessageDecodeDoubleDynArray(virNetMessage *msg, size_t maxlen, = double **v, size_t *len) +{ + VIR_NET_MESSAGE_DECODE_DYN_ARRAY_UINT64(double); +} + +void virNetMessageEncodeString(virNetMessage *msg, char *v) +{ + virNetMessageEncodeOpaqueDynArray(msg, (uint8_t *)v, strlen(v)); +} + +void virNetMessageDecodeString(virNetMessage *msg, size_t maxlen, char **v) +{ + size_t len; + virNetMessageDecodeOpaqueDynArray(msg, maxlen, (uint8_t **)v, &len); +} + +void virNetMessageEncodeOpaqueFixedArray(virNetMessage *msg, uint8_t *v, s= ize_t len) +{ + size_t pad =3D 4 - (len % 4); + + g_assert(len < (G_MAXUINT32 - 1)); + g_assert((G_MAXSIZE - len) > pad); + + virNetMessageEncodePrealloc(msg, len + pad); + memcpy(msg->buffer + msg->bufferOffset, v, len); + msg->bufferOffset +=3D len; + memset(msg->buffer + msg->bufferOffset, 0, pad); + msg->bufferOffset +=3D pad; +} + +void virNetMessageDecodeOpaqueFixedArray(virNetMessage *msg, uint8_t **v, = size_t len) +{ + size_t pad =3D 4 - (len % 4); + + g_assert(len < (G_MAXUINT32 - 1)); + g_assert((G_MAXSIZE - len) > pad); + + if (!virNetMessageDecodePending(msg, len + pad)) + return; + + memcpy(*v, msg->buffer + msg->bufferOffset, len); + msg->bufferOffset +=3D len + pad; +} + +void virNetMessageEncodeOpaqueDynArray(virNetMessage *msg, uint8_t *v, siz= e_t len) +{ + uint32_t lenp =3D htonl(len); + size_t pad =3D 4 - (len % 4); + + g_assert(len < (G_MAXUINT32 - 1)); + g_assert((G_MAXSIZE - len) > (pad + 4)); + + virNetMessageEncodePrealloc(msg, len + pad + sizeof(lenp)); + memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); + msg->bufferOffset +=3D sizeof(lenp); + memcpy(msg->buffer + msg->bufferOffset, v, len); + msg->bufferOffset +=3D len; + memset(msg->buffer + msg->bufferOffset, 0, pad); + msg->bufferOffset +=3D pad; +} + +void virNetMessageDecodeOpaqueDynArray(virNetMessage *msg, size_t maxlen, = uint8_t **v, size_t *len) +{ + uint32_t lentmp; + size_t pad; + + g_assert(maxlen < (G_MAXUINT32 - 1)); + + virNetMessageDecodeUInt32(msg, &lentmp); + if (msg->decodeErrno !=3D 0) + return; + + if (lentmp > maxlen) { + msg->decodeErrno =3D EFBIG; + return; + } + + pad =3D 4 - (lentmp % 4); + + if ((G_MAXSIZE - lentmp) <=3D pad) { + msg->decodeErrno =3D EFBIG; + return; + } + + if (!virNetMessageDecodePending(msg, lentmp + pad)) + return; + + *v =3D g_new0(uint8_t, lentmp); + *len =3D lentmp; + memcpy(*v, msg->buffer + msg->bufferOffset, lentmp); + msg->bufferOffset +=3D lentmp + pad; +} + + +void virNetMessageEncodeAnyFixedArray(virNetMessage *msg, void *v, size_t = len, size_t size, + virNetMessageEncoder encoder) +{ + char *vp =3D v; + while (len) { + encoder(msg, vp); + vp +=3D size; + len--; + } +} + +void virNetMessageDecodeAnyFixedArray(virNetMessage *msg, void **v, size_t= len, size_t size, + virNetMessageDecoder decoder) +{ + char *val =3D g_malloc0_n(size, len); + *v =3D val; + while (len) { + decoder(msg, (void **)&val); + val +=3D size; + len--; + } +} + +void virNetMessageEncodeAnyDynArray(virNetMessage *msg, void *v, size_t le= n, size_t size, + virNetMessageEncoder encoder) +{ + char *vp =3D v; + uint32_t lenp =3D htonl(len); + g_assert(len < (G_MAXUINT32 - 1)); + g_assert(((G_MAXSIZE - sizeof(uint32_t))/size) > len); + virNetMessageEncodePrealloc(msg, sizeof(uint32_t)); + memcpy(msg->buffer + msg->bufferOffset, &lenp, sizeof(lenp)); + msg->bufferOffset +=3D sizeof(lenp); + while (len) { + encoder(msg, vp); + vp +=3D size; + len--; + } +} + +void virNetMessageDecodeAnyDynArray(virNetMessage *msg, size_t maxlen, siz= e_t size, + virNetMessageDecoder decoder, void **v= , size_t *len) +{ + uint32_t lentmp; + char *vp; + virNetMessageDecodeUInt32(msg, &lentmp); + if (msg->decodeErrno !=3D 0) { + return; + } + if (lentmp > maxlen) { + msg->decodeErrno =3D EFBIG; + return; + } + g_assert(lentmp < (G_MAXUINT32 - 1)); + /* g_assert((G_MAXSIZE / size) > lentmp);*/ + *v =3D vp =3D g_malloc0_n(lentmp, size); + *len =3D lentmp; + while (lentmp) { + decoder(msg, (void**)&vp); + vp +=3D size; + lentmp--; + } +} + +int virNetMessageHasDecodeError(virNetMessage *msg) +{ + if (msg->decodeErrno) { + virReportSystemError(msg->decodeErrno, "%s", + _("Message terminated unexpectedly")); + return -1; + } + return 0; +} diff --git a/src/rpc/virnetmessage.h b/src/rpc/virnetmessage.h index 849674fa53..264ddd3c05 100644 --- a/src/rpc/virnetmessage.h +++ b/src/rpc/virnetmessage.h @@ -20,6 +20,7 @@ =20 #pragma once =20 +#include #include "virnetprotocol.h" =20 typedef struct _virNetMessage virNetMessage; @@ -28,6 +29,7 @@ typedef void (*virNetMessageFreeCallback)(virNetMessage *= msg, void *opaque); =20 struct _virNetMessage { bool tracked; + int decodeErrno; =20 char *buffer; /* Initially VIR_NET_MESSAGE_INITIAL + VIR_NET_MESSAGE_L= EN_MAX */ /* Maximum VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_L= EN_MAX */ @@ -94,3 +96,89 @@ int virNetMessageDupFD(virNetMessage *msg, =20 int virNetMessageAddFD(virNetMessage *msg, int fd); + +void virNetMessageEncodeInt8(virNetMessage *msg, int8_t v); +void virNetMessageDecodeInt8(virNetMessage *msg, int8_t *v); +void virNetMessageEncodeUInt8(virNetMessage *msg, uint8_t v); +void virNetMessageDecodeUInt8(virNetMessage *msg, uint8_t *v); +void virNetMessageEncodeInt16(virNetMessage *msg, int16_t v); +void virNetMessageDecodeInt16(virNetMessage *msg, int16_t *v); +void virNetMessageEncodeUInt16(virNetMessage *msg, uint16_t v); +void virNetMessageDecodeUInt16(virNetMessage *msg, uint16_t *v); +void virNetMessageEncodeInt32(virNetMessage *msg, int32_t v); +void virNetMessageDecodeInt32(virNetMessage *msg, int32_t *v); +void virNetMessageEncodeUInt32(virNetMessage *msg, uint32_t v); +void virNetMessageDecodeUInt32(virNetMessage *msg, uint32_t *v); +void virNetMessageEncodeInt64(virNetMessage *msg, int64_t v); +void virNetMessageDecodeInt64(virNetMessage *msg, int64_t *v); +void virNetMessageEncodeUInt64(virNetMessage *msg, uint64_t v); +void virNetMessageDecodeUInt64(virNetMessage *msg, uint64_t *v); + +void virNetMessageEncodeFloat(virNetMessage *msg, float v); +void virNetMessageDecodeFloat(virNetMessage *msg, float *v); +void virNetMessageEncodeDouble(virNetMessage *msg, double v); +void virNetMessageDecodeDouble(virNetMessage *msg, double *v); +void virNetMessageEncodeBool(virNetMessage *msg, bool v); +void virNetMessageDecodeBool(virNetMessage *msg, bool *v); + +void virNetMessageEncodeInt8FixedArray(virNetMessage *msg, int8_t *v, size= _t len); +void virNetMessageDecodeInt8FixedArray(virNetMessage *msg, int8_t **v, siz= e_t len); +void virNetMessageEncodeUInt8FixedArray(virNetMessage *msg, uint8_t *v, si= ze_t len); +void virNetMessageDecodeUInt8FixedArray(virNetMessage *msg, uint8_t **v, s= ize_t len); +void virNetMessageEncodeInt16FixedArray(virNetMessage *msg, int16_t *v, si= ze_t len); +void virNetMessageDecodeInt16FixedArray(virNetMessage *msg, int16_t **v, s= ize_t len); +void virNetMessageEncodeUInt16FixedArray(virNetMessage *msg, uint16_t *v, = size_t len); +void virNetMessageDecodeUInt16FixedArray(virNetMessage *msg, uint16_t **v,= size_t len); +void virNetMessageEncodeInt32FixedArray(virNetMessage *msg, int32_t *v, si= ze_t len); +void virNetMessageDecodeInt32FixedArray(virNetMessage *msg, int32_t **v, s= ize_t len); +void virNetMessageEncodeUInt32FixedArray(virNetMessage *msg, uint32_t *v, = size_t len); +void virNetMessageDecodeUInt32FixedArray(virNetMessage *msg, uint32_t **v,= size_t len); +void virNetMessageEncodeInt64FixedArray(virNetMessage *msg, int64_t *v, si= ze_t len); +void virNetMessageDecodeInt64FixedArray(virNetMessage *msg, int64_t **v, s= ize_t len); +void virNetMessageEncodeUInt64FixedArray(virNetMessage *msg, uint64_t *v, = size_t len); +void virNetMessageDecodeUInt64FixedArray(virNetMessage *msg, uint64_t **v,= size_t len); +void virNetMessageEncodeFloatFixedArray(virNetMessage *msg, float *v, size= _t len); +void virNetMessageDecodeFloatFixedArray(virNetMessage *msg, float **v, siz= e_t len); +void virNetMessageEncodeDoubleFixedArray(virNetMessage *msg, double *v, si= ze_t len); +void virNetMessageDecodeDoubleFixedArray(virNetMessage *msg, double **v, s= ize_t len); + +void virNetMessageEncodeInt8DynArray(virNetMessage *msg, int8_t *v, size_t= len); +void virNetMessageDecodeInt8DynArray(virNetMessage *msg, size_t maxlen, in= t8_t **v, size_t *len); +void virNetMessageEncodeUInt8DynArray(virNetMessage *msg, uint8_t *v, size= _t len); +void virNetMessageDecodeUInt8DynArray(virNetMessage *msg, size_t maxlen, u= int8_t **v, size_t *len); +void virNetMessageEncodeInt16DynArray(virNetMessage *msg, int16_t *v, size= _t len); +void virNetMessageDecodeInt16DynArray(virNetMessage *msg, size_t maxlen, i= nt16_t **v, size_t *len); +void virNetMessageEncodeUInt16DynArray(virNetMessage *msg, uint16_t *v, si= ze_t len); +void virNetMessageDecodeUInt16DynArray(virNetMessage *msg, size_t maxlen, = uint16_t **v, size_t *len); +void virNetMessageEncodeInt32DynArray(virNetMessage *msg, int32_t *v, size= _t len); +void virNetMessageDecodeInt32DynArray(virNetMessage *msg, size_t maxlen, i= nt32_t **v, size_t *len); +void virNetMessageEncodeUInt32DynArray(virNetMessage *msg, uint32_t *v, si= ze_t len); +void virNetMessageDecodeUInt32DynArray(virNetMessage *msg, size_t maxlen, = uint32_t **v, size_t *len); +void virNetMessageEncodeInt64DynArray(virNetMessage *msg, int64_t *v, size= _t len); +void virNetMessageDecodeInt64DynArray(virNetMessage *msg, size_t maxlen, i= nt64_t **v, size_t *len); +void virNetMessageEncodeUInt64DynArray(virNetMessage *msg, uint64_t *v, si= ze_t len); +void virNetMessageDecodeUInt64DynArray(virNetMessage *msg, size_t maxlen, = uint64_t **v, size_t *len); +void virNetMessageEncodeFloatDynArray(virNetMessage *msg, float *v, size_t= len); +void virNetMessageDecodeFloatDynArray(virNetMessage *msg, size_t maxlen, f= loat **v, size_t *len); +void virNetMessageEncodeDoubleDynArray(virNetMessage *msg, double *v, size= _t len); +void virNetMessageDecodeDoubleDynArray(virNetMessage *msg, size_t maxlen, = double **v, size_t *len); + +void virNetMessageEncodeString(virNetMessage *msg, char *v); +void virNetMessageDecodeString(virNetMessage *msg, size_t maxlen, char **v= ); +void virNetMessageEncodeOpaqueFixedArray(virNetMessage *msg, uint8_t *v, s= ize_t len); +void virNetMessageDecodeOpaqueFixedArray(virNetMessage *msg, uint8_t **v, = size_t len); +void virNetMessageEncodeOpaqueDynArray(virNetMessage *msg, uint8_t *v, siz= e_t len); +void virNetMessageDecodeOpaqueDynArray(virNetMessage *msg, size_t maxlen, = uint8_t **v, size_t *len); + +typedef void (*virNetMessageEncoder)(virNetMessage *msg, void *v); +typedef void (*virNetMessageDecoder)(virNetMessage *msg, void **v); +void virNetMessageEncodeAnyFixedArray(virNetMessage *msg, void *v, size_t = len, size_t size, + virNetMessageEncoder encoder); +void virNetMessageDecodeAnyFixedArray(virNetMessage *msg, void **v, size_t= len, size_t size, + virNetMessageDecoder decoder); +void virNetMessageEncodeAnyDynArray(virNetMessage *msg, void *v, size_t le= n, size_t size, + virNetMessageEncoder encoder); +void virNetMessageDecodeAnyDynArray(virNetMessage *msg, size_t maxlen, siz= e_t size, + virNetMessageDecoder decoder, void **v= , size_t *len); + +int virNetMessageHasDecodeError(virNetMessage *msg); --=20 2.39.1