~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/dnd/dndCPMsgV4.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2010 VMware, Inc. All rights reserved.
 
3
 *
 
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.
 
7
 *
 
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.
 
12
 *
 
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.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @dndCPMsgV4.c --
 
21
 *
 
22
 * Helper functions for DnDCPMsgV4.
 
23
 */
 
24
 
 
25
#include "vm_assert.h"
 
26
#include "dnd.h"
 
27
#include "dndClipboard.h"
 
28
#include "dndCPMsgV4.h"
 
29
#include "util.h"
 
30
 
 
31
 
 
32
/**
 
33
 * Check if received packet is valid or not.
 
34
 *
 
35
 * @param[in] packet
 
36
 * @param[in] packetSize
 
37
 *
 
38
 * @return TRUE if the packet is valid, FALSE otherwise.
 
39
 */
 
40
 
 
41
static Bool
 
42
DnDCPMsgV4IsPacketValid(const uint8 *packet,
 
43
                        size_t packetSize)
 
44
{
 
45
   DnDCPMsgHdrV4 *msgHdr = NULL;
 
46
   ASSERT(packet);
 
47
 
 
48
   if (packetSize < DND_CP_MSG_HEADERSIZE_V4) {
 
49
      return FALSE;
 
50
   }
 
51
 
 
52
   msgHdr = (DnDCPMsgHdrV4 *)packet;
 
53
 
 
54
   /* Payload size is not valid. */
 
55
   if (msgHdr->payloadSize > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
 
56
      return FALSE;
 
57
   }
 
58
 
 
59
   /* Binary size is not valid. */
 
60
   if (msgHdr->binarySize > DND_CP_MSG_MAX_BINARY_SIZE_V4) {
 
61
      return FALSE;
 
62
   }
 
63
 
 
64
   /* Payload size is more than binary size. */
 
65
   if (msgHdr->payloadOffset + msgHdr->payloadSize > msgHdr->binarySize) {
 
66
      return FALSE;
 
67
   }
 
68
 
 
69
   return TRUE;
 
70
}
 
71
 
 
72
 
 
73
/**
 
74
 * Initialize the DnDCPMsgV4.
 
75
 *
 
76
 * @param[in/out] msg DnDCPMsgV4 to be initialized.
 
77
 */
 
78
 
 
79
void
 
80
DnDCPMsgV4_Init(DnDCPMsgV4 *msg)
 
81
{
 
82
   ASSERT(msg);
 
83
   memset(msg, 0, sizeof(DnDCPMsgV4));
 
84
}
 
85
 
 
86
/**
 
87
 * Destroy the DnDCPMsgV4.
 
88
 *
 
89
 * @param[in/out] msg DnDCPMsgV4 to be destroyed.
 
90
 */
 
91
 
 
92
void
 
93
DnDCPMsgV4_Destroy(DnDCPMsgV4 *msg)
 
94
{
 
95
   if (msg) {
 
96
      free(msg->binary);
 
97
      DnDCPMsgV4_Init(msg);
 
98
   }
 
99
}
 
100
 
 
101
 
 
102
/**
 
103
 * Check the packet type.
 
104
 *
 
105
 * @param[in] packet
 
106
 * @param[in] packetSize
 
107
 *
 
108
 * @return DnDCPMsgPacketType
 
109
 */
 
110
 
 
111
DnDCPMsgPacketType DnDCPMsgV4_GetPacketType(const uint8 *packet,
 
112
                                            size_t packetSize)
 
113
{
 
114
   DnDCPMsgHdrV4 *msgHdr = NULL;
 
115
   ASSERT(packet);
 
116
 
 
117
   if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
 
118
      return DND_CP_MSG_PACKET_TYPE_INVALID;
 
119
   }
 
120
 
 
121
   msgHdr = (DnDCPMsgHdrV4 *)packet;
 
122
   if (msgHdr->binarySize <= DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
 
123
      return DND_CP_MSG_PACKET_TYPE_SINGLE;
 
124
   }
 
125
 
 
126
   if (0 == msgHdr->payloadOffset) {
 
127
      return DND_CP_MSG_PACKET_TYPE_MULTIPLE_NEW;
 
128
   }
 
129
 
 
130
   if (msgHdr->payloadOffset + msgHdr->payloadSize == msgHdr->binarySize) {
 
131
      return DND_CP_MSG_PACKET_TYPE_MULTIPLE_END;
 
132
   }
 
133
 
 
134
   return DND_CP_MSG_PACKET_TYPE_MULTIPLE_CONTINUE;
 
135
}
 
136
 
 
137
 
 
138
/**
 
139
 * Serialize the msg to packet.
 
140
 *
 
141
 * @param[in/out] msg DnDCPMsgV4 to be serialized from.
 
142
 * @param[out] packet DnDCPMsgV4 to be serialized to.
 
143
 * @param[out] packetSize serialized packet size.
 
144
 *
 
145
 * @return TRUE if succeed, FALSE otherwise.
 
146
 */
 
147
 
 
148
Bool
 
149
DnDCPMsgV4_Serialize(DnDCPMsgV4 *msg,
 
150
                     uint8 **packet,
 
151
                     size_t *packetSize)
 
152
{
 
153
   size_t payloadSize = 0;
 
154
 
 
155
   ASSERT(msg);
 
156
   ASSERT(packet);
 
157
   ASSERT(packetSize);
 
158
   ASSERT(msg->hdr.binarySize >= msg->hdr.payloadOffset);
 
159
 
 
160
   if (msg->hdr.binarySize <= DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
 
161
      /*
 
162
       * One single packet is enough for the message. For short message, the
 
163
       * payloadOffset should always be 0.
 
164
       */
 
165
      ASSERT(msg->hdr.payloadOffset == 0);
 
166
      payloadSize = msg->hdr.binarySize;
 
167
   } else {
 
168
      /* For big message, payloadOffset means binary size we already sent out. */
 
169
      if (msg->hdr.binarySize - msg->hdr.payloadOffset > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
 
170
         payloadSize = DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4;
 
171
      } else {
 
172
         payloadSize = msg->hdr.binarySize - msg->hdr.payloadOffset;
 
173
      }
 
174
   }
 
175
 
 
176
   *packetSize = DND_CP_MSG_HEADERSIZE_V4 + payloadSize;
 
177
   *packet = Util_SafeMalloc(*packetSize);
 
178
   memcpy(*packet, msg, DND_CP_MSG_HEADERSIZE_V4);
 
179
   if (payloadSize > 0) {
 
180
      memcpy(*packet + DND_CP_MSG_HEADERSIZE_V4,
 
181
             msg->binary + msg->hdr.payloadOffset,
 
182
             payloadSize);
 
183
   }
 
184
   ((DnDCPMsgHdrV4 *)(*packet))->payloadSize = payloadSize;
 
185
   /* Next DnDCPMsgV4_Serialize will use this payloadOffset to get unsent binary. */
 
186
   msg->hdr.payloadOffset += payloadSize;
 
187
   return TRUE;
 
188
}
 
189
 
 
190
 
 
191
/**
 
192
 * Unserialize the packet to DnDCPMsgV4 for short messsage.
 
193
 *
 
194
 * @param[in/out] msg DnDCPMsgV4 to be unserialized to.
 
195
 * @param[in] packet DnDCPMsgV4 to be unserialized from.
 
196
 * @param[in] packetSize
 
197
 *
 
198
 * @return TRUE if succeed, FALSE otherwise.
 
199
 */
 
200
 
 
201
Bool
 
202
DnDCPMsgV4_UnserializeSingle(DnDCPMsgV4 *msg,
 
203
                             const uint8 *packet,
 
204
                             size_t packetSize)
 
205
{
 
206
   DnDCPMsgHdrV4 *msgHdr = NULL;
 
207
   ASSERT(msg);
 
208
   ASSERT(packet);
 
209
 
 
210
   if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
 
211
      return FALSE;
 
212
   }
 
213
 
 
214
   msgHdr = (DnDCPMsgHdrV4 *)packet;
 
215
 
 
216
   /* Offset should be 0 for short message. */
 
217
   if (msgHdr->payloadOffset != 0) {
 
218
      return FALSE;
 
219
   }
 
220
 
 
221
   memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4);
 
222
 
 
223
   if (msg->hdr.binarySize != 0) {
 
224
      msg->binary = Util_SafeMalloc(msg->hdr.binarySize);
 
225
 
 
226
      memcpy(msg->binary,
 
227
             packet + DND_CP_MSG_HEADERSIZE_V4,
 
228
             msg->hdr.payloadSize);
 
229
      msg->hdr.payloadOffset = msg->hdr.payloadSize;
 
230
   }
 
231
   return TRUE;
 
232
}
 
233
 
 
234
 
 
235
/**
 
236
 * Unserialize the packet to DnDCPMsgV4 for big messsage.
 
237
 *
 
238
 * @param[in/out] msg DnDCPMsgV4 to be unserialized to.
 
239
 * @param[in] packet DnDCPMsgV4 to be unserialized from.
 
240
 * @param[in] packetSize
 
241
 *
 
242
 * @return TRUE if succeed, FALSE otherwise.
 
243
 */
 
244
 
 
245
Bool
 
246
DnDCPMsgV4_UnserializeMultiple(DnDCPMsgV4 *msg,
 
247
                               const uint8 *packet,
 
248
                               size_t packetSize)
 
249
{
 
250
   DnDCPMsgHdrV4 *msgHdr = NULL;
 
251
   ASSERT(msg);
 
252
   ASSERT(packet);
 
253
 
 
254
   if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {
 
255
      return FALSE;
 
256
   }
 
257
 
 
258
   msgHdr = (DnDCPMsgHdrV4 *)packet;
 
259
 
 
260
   /*
 
261
    * For each session, there is at most 1 big message. If the received
 
262
    * sessionId is different with buffered one, the received packet is for
 
263
    * another another new message. Destroy old buffered message.
 
264
    */
 
265
   if (msg->binary &&
 
266
       msg->hdr.sessionId != msgHdr->sessionId) {
 
267
      DnDCPMsgV4_Destroy(msg);
 
268
   }
 
269
 
 
270
   /* Offset should be 0 for new message. */
 
271
   if (NULL == msg->binary && msgHdr->payloadOffset != 0) {
 
272
      return FALSE;
 
273
   }
 
274
 
 
275
   /* For existing buffered message, the payload offset should match. */
 
276
   if (msg->binary &&
 
277
       msg->hdr.sessionId == msgHdr->sessionId &&
 
278
       msg->hdr.payloadOffset != msgHdr->payloadOffset) {
 
279
      return FALSE;
 
280
   }
 
281
 
 
282
   if (NULL == msg->binary) {
 
283
      memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4);
 
284
      msg->binary = Util_SafeMalloc(msg->hdr.binarySize);
 
285
   }
 
286
 
 
287
   /* msg->hdr.payloadOffset is used as received binary size. */
 
288
   memcpy(msg->binary + msg->hdr.payloadOffset,
 
289
          packet + DND_CP_MSG_HEADERSIZE_V4,
 
290
          msgHdr->payloadSize);
 
291
   msg->hdr.payloadOffset += msgHdr->payloadSize;
 
292
   return TRUE;
 
293
}
 
294
 
 
295
 
 
296
/**
 
297
 * Map a command to a string.
 
298
 *
 
299
 * @param[in] cmd the DnD V4 command
 
300
 *
 
301
 * @return a valid command string if the command is valid, "invalid command"
 
302
 *         otherwise.
 
303
 */
 
304
 
 
305
const char *
 
306
DnDCPMsgV4_LookupCmd(uint32 cmd)
 
307
{
 
308
   static const struct {
 
309
      uint32 cmd;
 
310
      const char *cmdStr;
 
311
   } cmdStringTable[] = {
 
312
      { DNDCP_CMD_PING,                "DNDCP_CMD_PING" },
 
313
      { DNDCP_CMD_PING_REPLY,          "DNDCP_CMD_PING_REPLY" },
 
314
      { DNDCP_CMD_REQUEST_NEXT,        "DNDCP_CMD_REQUEST_NEXT" },
 
315
      { DNDCP_CMP_REPLY,               "DNDCP_CMP_REPLY" },
 
316
      { DNDCP_CMD_TEST_BIG_BINARY,     "DNDCP_CMD_TEST_BIG_BINARY" },
 
317
      { DNDCP_CMD_TEST_BIG_BINARY_REPLY, "DNDCP_CMD_TEST_BIG_BINARY_REPLY" },
 
318
 
 
319
      { DND_CMD_DEST_DRAG_ENTER,       "DND_CMD_DEST_DRAG_ENTER" },
 
320
      { DND_CMD_DEST_DRAG_ENTER_REPLY, "DND_CMD_DEST_DRAG_ENTER_REPLY" },
 
321
      { DND_CMD_DEST_SEND_CLIPBOARD,   "DND_CMD_DEST_SEND_CLIPBOARD" },
 
322
      { DND_CMD_DEST_DRAG_LEAVE,       "DND_CMD_DEST_DRAG_LEAVE" },
 
323
      { DND_CMD_DEST_DROP,             "DND_CMD_DEST_DROP" },
 
324
      { DND_CMD_SRC_DRAG_BEGIN,        "DND_CMD_SRC_DRAG_BEGIN" },
 
325
      { DND_CMD_SRC_DRAG_BEGIN_DONE,   "DND_CMD_SRC_DRAG_BEGIN_DONE" },
 
326
      { DND_CMD_SRC_DROP,              "DND_CMD_SRC_DROP" },
 
327
      { DND_CMD_SRC_DROP_DONE,         "DND_CMD_SRC_DROP_DONE" },
 
328
      { DND_CMD_SRC_CANCEL,            "DND_CMD_SRC_CANCEL" },
 
329
      { DND_CMD_PRIV_DRAG_ENTER,       "DND_CMD_PRIV_DRAG_ENTER" },
 
330
      { DND_CMD_PRIV_DRAG_LEAVE,       "DND_CMD_PRIV_DRAG_LEAVE" },
 
331
      { DND_CMD_PRIV_DROP,             "DND_CMD_PRIV_DROP" },
 
332
      { DND_CMD_MOVE_MOUSE,            "DND_CMD_MOVE_MOUSE" },
 
333
      { DND_CMD_UPDATE_FEEDBACK,       "DND_CMD_UPDATE_FEEDBACK" },
 
334
      { DND_CMD_REQUEST_FILES,         "DND_CMD_REQUEST_FILES" },
 
335
      { DND_CMD_GET_FILES_DONE,        "DND_CMD_GET_FILES_DONE" },
 
336
      { DND_CMD_SEND_FILES_DONE,       "DND_CMD_SEND_FILES_DONE" },
 
337
      { DND_CMD_QUERY_EXITING,         "DND_CMD_QUERY_EXITING" },
 
338
      { DND_CMD_DRAG_NOT_PENDING,      "DND_CMD_DRAG_NOT_PENDING" },
 
339
      { DND_CMD_UPDATE_UNITY_DET_WND,  "DND_CMD_UPDATE_UNITY_DET_WND" },
 
340
 
 
341
      { CP_CMD_REQUEST_CLIPBOARD,      "CP_CMD_REQUEST_CLIPBOARD" },
 
342
      { CP_CMD_REQUEST_FILES,          "CP_CMD_REQUEST_FILES" },
 
343
      { CP_CMD_RECV_CLIPBOARD,         "CP_CMD_RECV_CLIPBOARD" },
 
344
      { CP_CMD_SEND_CLIPBOARD,         "CP_CMD_SEND_CLIPBOARD" },
 
345
      { CP_CMD_GET_FILES_DONE,         "CP_CMD_GET_FILES_DONE" },
 
346
      { CP_CMD_SEND_FILES_DONE,        "CP_CMD_SEND_FILES_DONE" },
 
347
 
 
348
      { FT_CMD_HGFS_REQUEST,           "FT_CMD_HGFS_REQUEST" },
 
349
      { FT_CMD_HGFS_REPLY,             "FT_CMD_HGFS_REPLY" },
 
350
      { FT_CMD_UPDATE_PROGRESS,        "FT_CMD_UPDATE_PROGRESS" },
 
351
      { FT_CMD_PROGRESS_REPLY,         "FT_CMD_PROGRESS_REPLY" },
 
352
   };
 
353
   size_t i;
 
354
 
 
355
   for (i = 0; i < ARRAYSIZE(cmdStringTable); i++) {
 
356
      if (cmdStringTable[i].cmd == cmd) {
 
357
         return cmdStringTable[i].cmdStr;
 
358
      }
 
359
   }
 
360
   return "invalid command";
 
361
}
 
362