~ubuntu-branches/ubuntu/precise/open-vm-tools/precise

« back to all changes in this revision

Viewing changes to modules/linux/vmci/vmciGuestDs.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) 2007 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 General Public License as published by the
6
 
 * Free Software Foundation version 2 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 GNU General Public License
11
 
 * for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License along
14
 
 * 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
 
 * vmciGuestDs.c
21
 
 *
22
 
 * Implements the client-access API to the VMCI discovery service in
23
 
 * the guest kernel.
24
 
 *
25
 
 */
26
 
 
27
 
#ifdef __linux__
28
 
#  include "driver-config.h"
29
 
 
30
 
#  define EXPORT_SYMTAB
31
 
 
32
 
#  include <linux/module.h>
33
 
#  include "compat_kernel.h"
34
 
#  include "compat_pci.h"
35
 
#elif defined(_WIN32)
36
 
#  include <ntddk.h>
37
 
#elif defined(SOLARIS)
38
 
#  include <sys/ddi.h>
39
 
#  include <sys/sunddi.h>
40
 
#elif defined(__APPLE__)
41
 
#  include <IOKit/IOLib.h>
42
 
#else
43
 
#  error "Platform not support by VMCI datagram API."
44
 
#endif // linux
45
 
 
46
 
#include "vm_basic_types.h"
47
 
#include "vm_atomic.h"
48
 
#include "vm_assert.h"
49
 
#include "vmci_defs.h"
50
 
#include "vmci_kernel_if.h"
51
 
#include "vmci_infrastructure.h"
52
 
#include "vmciInt.h"
53
 
#include "vmciUtil.h"
54
 
#include "vmciDatagram.h"
55
 
#include "vmciKernelAPI.h"
56
 
 
57
 
static Atomic_uint32 MsgIdCounter = { 0 };
58
 
 
59
 
typedef struct VMCIDsRecvData {
60
 
   VMCIHost context;
61
 
   VMCILock lock;
62
 
   int status;
63
 
   uint8 buffer[VMCI_DS_MAX_MSG_SIZE];
64
 
} VMCIDsRecvData;
65
 
 
66
 
static int VMCIDsDoCall(int action, const char *name, VMCIHandle handle,
67
 
                        VMCIHandle *handleOut);
68
 
static int VMCIDsRecvCB(void *clientData, struct VMCIDatagram *msg);
69
 
 
70
 
/*
71
 
 *-------------------------------------------------------------------------
72
 
 *
73
 
 *  VMCIDs_Lookup --
74
 
 *
75
 
 *       Look up a handle in the VMCI discovery service based on
76
 
 *       the given name.
77
 
 *
78
 
 *  Results:
79
 
 *       Error code. 0 if success.
80
 
 *
81
 
 *  Side effects:
82
 
 *       None.
83
 
 *
84
 
 *-------------------------------------------------------------------------
85
 
 */
86
 
 
87
 
#ifdef __linux__
88
 
EXPORT_SYMBOL(VMCIDs_Lookup);
89
 
#endif
90
 
 
91
 
int
92
 
VMCIDs_Lookup(const char *name,   // IN
93
 
              VMCIHandle *out)    //
94
 
{
95
 
   return VMCIDsDoCall(VMCI_DS_ACTION_LOOKUP, name, VMCI_INVALID_HANDLE, out);
96
 
}
97
 
 
98
 
 
99
 
/*
100
 
 *-------------------------------------------------------------------------
101
 
 *
102
 
 *  VMCIDsDoCall --
103
 
 *
104
 
 *       Serialize a call into the CDS wire-format, send it across
105
 
 *       the VMCI device, wait for a response, and return
106
 
 *       the results.
107
 
 *
108
 
 *  Results:
109
 
 *       Error code. 0 if success.
110
 
 *
111
 
 *  Side effects:
112
 
 *       None.
113
 
 *
114
 
 *-------------------------------------------------------------------------
115
 
 */
116
 
 
117
 
 
118
 
static int
119
 
VMCIDsDoCall(int action,            // IN
120
 
             const char *name,      // IN
121
 
             VMCIHandle handle,     // IN: For the "register" action
122
 
             VMCIHandle *handleOut) // OUT: For the "lookup" action
123
 
{
124
 
   int8 *sendBuffer = NULL;
125
 
   const size_t sendBufferSize = VMCI_DS_MAX_MSG_SIZE + sizeof(VMCIDatagram);
126
 
   int nameLen, requestSize, res;
127
 
   uint32 savedMsgIdCounter;
128
 
   VMCIDsReplyHeader *reply;
129
 
   VMCIHandle dsHandle = VMCI_INVALID_HANDLE;
130
 
   VMCIDsRecvData *recvData = NULL;
131
 
   VMCIDatagram *dgram;
132
 
   VMCIDsRequestHeader *request;
133
 
   VMCILockFlags flags;
134
 
 
135
 
   nameLen = strlen(name);
136
 
   if (nameLen + sizeof *request > sendBufferSize) {
137
 
      res = VMCI_ERROR_INVALID_ARGS;
138
 
      goto out;
139
 
   }
140
 
 
141
 
   sendBuffer = VMCI_AllocKernelMem(sendBufferSize, VMCI_MEMORY_NONPAGED);
142
 
   if (sendBuffer == NULL) {
143
 
      res = VMCI_ERROR_NO_MEM;
144
 
      goto out;
145
 
   }
146
 
 
147
 
   recvData = VMCI_AllocKernelMem(sizeof *recvData, VMCI_MEMORY_NONPAGED);
148
 
   if (recvData == NULL) {
149
 
      res = VMCI_ERROR_NO_MEM;
150
 
      goto out;
151
 
   }
152
 
 
153
 
   VMCIHost_InitContext(&recvData->context, (uintptr_t) recvData);
154
 
   VMCI_InitLock(&recvData->lock, "VMCIDsRecvHandler", VMCI_LOCK_RANK_MIDDLE_BH);
155
 
 
156
 
   savedMsgIdCounter = Atomic_FetchAndInc(&MsgIdCounter);
157
 
 
158
 
   dgram = (VMCIDatagram *) sendBuffer;
159
 
   request = (VMCIDsRequestHeader *) (sendBuffer + sizeof *dgram);
160
 
 
161
 
   /* Serialize request. */
162
 
   request->action = action;
163
 
   request->msgid = savedMsgIdCounter;
164
 
   request->handle = handle;
165
 
   request->nameLen = nameLen;
166
 
   memcpy(request->name, name, nameLen + 1);
167
 
 
168
 
   requestSize = sizeof *request + nameLen;
169
 
 
170
 
   if (VMCIDatagram_CreateHnd(VMCI_INVALID_ID, 0, VMCIDsRecvCB,
171
 
                              recvData, &dsHandle) != VMCI_SUCCESS) {
172
 
      res = VMCI_ERROR_NO_HANDLE;
173
 
      goto out;
174
 
   }
175
 
 
176
 
   dgram->dst = VMCI_DS_HANDLE;
177
 
   dgram->src = dsHandle;
178
 
   dgram->payloadSize = requestSize;
179
 
 
180
 
   /* Send the datagram to CDS. */
181
 
   res = VMCIDatagram_Send(dgram);
182
 
   if (res <=  0) {
183
 
      goto out;
184
 
   }
185
 
 
186
 
   /* Block here waiting for the reply */
187
 
   VMCI_GrabLock_BH(&recvData->lock, &flags);
188
 
   VMCIHost_WaitForCallLocked(&recvData->context, &recvData->lock, &flags, TRUE);
189
 
   VMCI_ReleaseLock_BH(&recvData->lock, flags);
190
 
 
191
 
   if (recvData->status != VMCI_SUCCESS) {
192
 
      res = recvData->status;
193
 
      goto out;
194
 
   }
195
 
 
196
 
   reply = (VMCIDsReplyHeader *) recvData->buffer;
197
 
   /* Check that the msgid matches what we expect. */
198
 
   if (reply->msgid != savedMsgIdCounter) {
199
 
      res = VMCI_ERROR_GENERIC;
200
 
      goto out;
201
 
   }
202
 
 
203
 
   if (handleOut != NULL) {
204
 
      *handleOut = reply->handle;
205
 
   }
206
 
 
207
 
   res = reply->code;
208
 
 
209
 
out:
210
 
   if (!VMCI_HANDLE_EQUAL(dsHandle, VMCI_INVALID_HANDLE)) {
211
 
      VMCIDatagram_DestroyHnd(dsHandle);
212
 
   }
213
 
   if (recvData) {
214
 
      VMCI_CleanupLock(&recvData->lock);
215
 
      VMCIHost_ReleaseContext(&recvData->context);
216
 
      VMCI_FreeKernelMem(recvData, sizeof *recvData);
217
 
   }
218
 
   if (sendBuffer) {
219
 
      VMCI_FreeKernelMem(sendBuffer, sendBufferSize);
220
 
   }
221
 
   return res;
222
 
}
223
 
 
224
 
/*
225
 
 *-----------------------------------------------------------------------------
226
 
 *
227
 
 * VMCIDsRecvCB --
228
 
 *
229
 
 *      Receive callback for the Discovery Service query datagram
230
 
 *      handle.
231
 
 *
232
 
 * Results:
233
 
 *      If the received payload is not larger than the MAX, it is
234
 
 *      copied into clientData.
235
 
 *
236
 
 * Side effects:
237
 
 *      Signals the thread waiting for the reply.
238
 
 *
239
 
 *-----------------------------------------------------------------------------
240
 
 */
241
 
 
242
 
 
243
 
static int
244
 
VMCIDsRecvCB(void *clientData,          // IN: client data for handler
245
 
             struct VMCIDatagram *msg)  // IN
246
 
{
247
 
   VMCIDsRecvData *recvData = clientData;
248
 
   VMCILockFlags flags;
249
 
 
250
 
   ASSERT(msg->payloadSize <= VMCI_DS_MAX_MSG_SIZE);
251
 
   if (msg->payloadSize <= VMCI_DS_MAX_MSG_SIZE) {
252
 
      memcpy(recvData->buffer, VMCI_DG_PAYLOAD(msg), (size_t)msg->payloadSize);
253
 
      recvData->status = VMCI_SUCCESS;
254
 
   } else {
255
 
      recvData->status = VMCI_ERROR_PAYLOAD_TOO_LARGE;
256
 
   }
257
 
 
258
 
   VMCI_GrabLock_BH(&recvData->lock, &flags);
259
 
   VMCIHost_SignalCall(&recvData->context);
260
 
   VMCI_ReleaseLock_BH(&recvData->lock, flags);
261
 
   return 0;
262
 
}