1
/*********************************************************
2
* Copyright (C) 2007 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
22
* DnDMsg represents an rpc message which is sent across the
23
* wire. Any args that it holds will be written out exactly as stored.
25
* To protect itself there are many checks to ensure the data which is
26
* serialized and unserialized is sane. Defines and asserts are used to
27
* ensure the message stays under these limits when serializing out and
28
* checks are enforced to ensure that the data to be unserialized remains
34
#include "vm_assert.h"
39
#define LOGLEVEL_MODULE dnd
40
#include "loglevel_user.h"
44
*----------------------------------------------------------------------------
56
*----------------------------------------------------------------------------
60
DnDMsg_Init(DnDMsg *msg) // IN/OUT: the message
67
DynBufArray_Init(&msg->args, 0);
68
msg->expectedArgsSz = 0;
73
*----------------------------------------------------------------------------
77
* Destroys a message by clearing any of the data that is contained in it.
83
* Frees the arguments' memory.
85
*----------------------------------------------------------------------------
89
DnDMsg_Destroy(DnDMsg *msg) // IN/OUT: the message
96
count = DynArray_Count(&msg->args);
101
msg->expectedArgsSz = 0;
103
for (i = 0; i < count; ++i) {
104
DynBuf *b = DynArray_AddressOf(&msg->args, i);
107
DynArray_SetCount(&msg->args, 0);
108
DynBufArray_Destroy(&msg->args);
113
*----------------------------------------------------------------------------
117
* Gets the dnd/copy paste command from the header.
120
* An uint32 representing the command.
125
*----------------------------------------------------------------------------
129
DnDMsg_GetCmd(DnDMsg *msg) // IN/OUT: the message
138
*----------------------------------------------------------------------------
142
* Sets the command for the message.
150
*----------------------------------------------------------------------------
154
DnDMsg_SetCmd(DnDMsg *msg, // IN/OUT: the message
155
uint32 cmd) // IN: the command
158
ASSERT((DND_INVALID < cmd && cmd < DND_MAX) ||
159
(CP_INVALID < cmd && cmd < CP_MAX));
166
*----------------------------------------------------------------------------
170
* Determines the number of arguments currently in the DnDMsg.
173
* The number of arguments.
178
*----------------------------------------------------------------------------
182
DnDMsg_NumArgs(DnDMsg *msg) // IN/OUT: the message
186
return DynBufArray_Count(&msg->args);
191
*----------------------------------------------------------------------------
195
* Gets an argument stored in DnDMsg.
198
* Null if the argument is out of bounds, otherwise a pointer to a dynbuf
199
* containing the argument.
200
* This dynbuf is still
201
* managed by the DnDMsg and should NOT be destroyed.
206
*----------------------------------------------------------------------------
210
DnDMsg_GetArg(DnDMsg *msg, // IN/OUT: the message
211
uint32 idx) // IN: the argument to return
214
ASSERT(0 <= idx && idx < DynBufArray_Count(&msg->args));
216
return DynArray_AddressOf(&msg->args, idx);
221
*----------------------------------------------------------------------------
223
* DnDMsg_AppendArg --
225
* Adds the data to the end of the argument list in the message. It will
226
* create a copy of the data to be mananged by DnDMsg until the message is
230
* TRUE on success, FALSE on failure.
233
* Increases the internal arg size counter.
235
*----------------------------------------------------------------------------
239
DnDMsg_AppendArg(DnDMsg *msg, // IN/OUT: the message
240
void *buf, // IN: the input buffer
241
size_t len) // IN: the length of the input buffer
248
if (DynBufArray_Count(&msg->args) >= DNDMSG_MAX_ARGS) {
252
DynBuf_Init(&clonebuf);
253
if (!DynBuf_Append(&clonebuf, buf, len)) {
257
/* The dynbufarray now owns the clonebuf data. */
258
if (!DynBufArray_Push(&msg->args, clonebuf)) {
264
DynBuf_Destroy(&clonebuf);
270
*----------------------------------------------------------------------------
272
* DnDMsg_Serialize --
274
* Serialize the contents of the DnDMsg out to the provided dynbuf. It
275
* will ASSERT if any invariants are broken.
284
*----------------------------------------------------------------------------
288
DnDMsg_Serialize(DnDMsg *msg, // IN/OUT: the message
289
DynBuf* buf) // OUT: the output buffer
294
uint32 serializeArgsSz = 0;
298
ASSERT((DND_INVALID < msg->cmd && msg->cmd < DND_MAX) ||
299
(CP_INVALID < msg->cmd && msg->cmd < CP_MAX));
301
nargs = DynBufArray_Count(&msg->args);
303
for (i = 0; i < nargs; ++i) {
304
DynBuf *b = DynArray_AddressOf(&msg->args, i);
305
serializeArgsSz += sizeof(uint32) + DynBuf_GetSize(b);
308
if (DynBuf_Append(buf, &msg->ver, sizeof msg->ver) &&
309
DynBuf_Append(buf, &msg->cmd, sizeof msg->cmd) &&
310
DynBuf_Append(buf, &nargs, sizeof nargs) &&
311
DynBuf_Append(buf, &serializeArgsSz, sizeof serializeArgsSz)) {
315
for (i = 0; i < nargs; i++) {
316
curArg = DynBufArray_AddressOf(&msg->args, i);
317
curArgsSz = DynBuf_GetSize(curArg);
319
if (!DynBuf_Append(buf, &curArgsSz, sizeof curArgsSz) ||
320
!DynBuf_Append(buf, DynBuf_Get(curArg), curArgsSz)) {
333
*----------------------------------------------------------------------------
335
* DnDMsg_UnserializeHeader --
337
* Read the header from the buffer into a DnDMsg. Any contents in the
338
* DnDMsg will be destroyed. This allows you to retrieve header
339
* information. These functions are specified in the dndMsg.h. Most
340
* notably, you can retrieve the size of the arguments so that you can
341
* pass a properly sized buffer to DnDMsg_UnserializeArgs.
343
* This is the one of the two places that nargs is set. The other is
344
* implicitly set by DnDMsg_AppendArg with the push and only ever
345
* realized through the DnDMsg_Serialize function. expectedArgsSz,
346
* curArgSz follows the same idea.
349
* DNDMSG_SUCCESS on success.
350
* DNDMSG_INPUT_TOO_SMALL when provided buffer is too small.
351
* DNDMSG_INPUT_ERR when the provided buffer is inconsistant.
352
* DNDMSG_NOMEM when we run out of memory.
353
* DNDMSG_ERR on any other error.
356
* On success the msg's header will be filled. On failure the msg will be
359
*----------------------------------------------------------------------------
363
DnDMsg_UnserializeHeader(DnDMsg *msg, // IN/OUT: the message
364
void *buf, // IN: the input buffer
365
size_t len) // IN: the buffer length
375
if (len < DNDMSG_HEADERSIZE_V3) {
376
return DNDMSG_INPUT_TOO_SMALL;
379
/* Read buffer into msg. */
380
if (DnDReadBuffer(&r, &msg->ver, sizeof msg->ver) &&
381
DnDReadBuffer(&r, &msg->cmd, sizeof msg->cmd) &&
382
DnDReadBuffer(&r, &msg->nargs, sizeof msg->nargs) &&
383
DnDReadBuffer(&r, &msg->expectedArgsSz, sizeof msg->expectedArgsSz)) {
385
if (msg->expectedArgsSz < DNDMSG_MAX_ARGSZ &&
386
(msg->cmd < DND_MAX || msg->cmd < CP_MAX) &&
389
msg->nargs < DNDMSG_MAX_ARGS) {
390
return DNDMSG_SUCCESS;
392
return DNDMSG_INPUT_ERR;
395
return DNDMSG_INPUT_TOO_SMALL;
401
*----------------------------------------------------------------------------
403
* DnDMsg_UnserializeArgs --
405
* Unserialize the arguments of the message provided by the buffer.
406
* Each argument is a uint32 of the size followed by the buffer. On
407
* failure the message will revert to the state which was passed into the
411
* DNDMSG_SUCCESS on success.
412
* DNDMSG_INPUT_TOO_SMALL when provided buffer is too small.
413
* DNDMSG_INPUT_ERR when the provided buffer is inconsistant.
414
* DNDMSG_NOMEM when we run out of memory.
415
* DNDMSG_ERR on any other error.
418
* On success, arguments found in buf are unserialized into msg.
420
*----------------------------------------------------------------------------
424
DnDMsg_UnserializeArgs(DnDMsg *msg, // IN/OUT: the message
425
void *buf, // IN: input buffer
426
size_t len) // IN: buffer length
431
uint32 readArgsSz = 0;
434
DnDMsgErr ret = DNDMSG_SUCCESS;
437
ASSERT(DynBufArray_Count(&msg->args) == 0);
443
if (len < msg->expectedArgsSz) {
444
return DNDMSG_INPUT_TOO_SMALL;
447
for (i = 0; i < msg->nargs; ++i) {
449
if (!DnDReadBuffer(&r, &argSz, sizeof argSz)) {
450
ret = DNDMSG_INPUT_TOO_SMALL;
454
if (argSz > DNDMSG_MAX_ARGSZ ||
455
readArgsSz + sizeof (uint32) + argSz > msg->expectedArgsSz) {
456
ret = DNDMSG_INPUT_ERR;
460
data = malloc(argSz);
466
if (!DnDReadBuffer(&r, data, argSz)) {
471
if (!DnDMsg_AppendArg(msg, data, argSz)) {
475
readArgsSz += argSz + sizeof (uint32);
479
ASSERT(ret == DNDMSG_SUCCESS);
487
count = DynBufArray_Count(&msg->args);
488
for (i = 0; i < count; ++i) {
489
DynBuf *b = DynArray_AddressOf(&msg->args, i);
493
* DnDMsg_AppendArg relies on DynBufArray_Push, hence the count needs to be
496
DynBufArray_SetCount(&msg->args, 0);