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

« back to all changes in this revision

Viewing changes to modules/linux/vmci/common/vmciDatagram.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) 2006 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
 * vmciDatagram.c --
 
21
 *
 
22
 *    This file implements the VMCI Simple Datagram API on the host.
 
23
 */
 
24
 
 
25
#include "vmci_kernel_if.h"
 
26
#include "vm_assert.h"
 
27
#include "vmci_defs.h"
 
28
#include "vmci_infrastructure.h"
 
29
#include "vmciCommonInt.h"
 
30
#include "vmciContext.h"
 
31
#include "vmciDatagram.h"
 
32
#include "vmciDriver.h"
 
33
#include "vmciEvent.h"
 
34
#include "vmciHashtable.h"
 
35
#include "vmciKernelAPI.h"
 
36
#include "vmciResource.h"
 
37
#include "vmciRoute.h"
 
38
#if defined(VMKERNEL)
 
39
#  include "vmciVmkInt.h"
 
40
#  include "vm_libc.h"
 
41
#  include "helper_ext.h"
 
42
#endif
 
43
 
 
44
#define LGPFX "VMCIDatagram: "
 
45
 
 
46
 
 
47
/*
 
48
 * DatagramEntry describes the datagram entity. It is used for datagram
 
49
 * entities created only on the host.
 
50
 */
 
51
typedef struct DatagramEntry {
 
52
   VMCIResource        resource;
 
53
   uint32              flags;
 
54
   Bool                runDelayed;
 
55
   VMCIDatagramRecvCB  recvCB;
 
56
   void                *clientData;
 
57
   VMCIEvent           destroyEvent;
 
58
   VMCIPrivilegeFlags  privFlags;
 
59
} DatagramEntry;
 
60
 
 
61
/* Mapping between wellknown resource and context. */
 
62
typedef struct DatagramWKMapping {
 
63
   VMCIHashEntry entry;
 
64
   VMCIId        contextID;
 
65
} DatagramWKMapping;
 
66
 
 
67
typedef struct VMCIDelayedDatagramInfo {
 
68
   Bool inDGHostQueue;
 
69
   DatagramEntry *entry;
 
70
   VMCIDatagram msg;
 
71
} VMCIDelayedDatagramInfo;
 
72
 
 
73
 
 
74
/* Wellknown mapping hashtable. */
 
75
static VMCIHashTable *wellKnownTable = NULL;
 
76
 
 
77
static Atomic_uint32 delayedDGHostQueueSize;
 
78
 
 
79
static int VMCIDatagramGetPrivFlagsInt(VMCIId contextID, VMCIHandle handle,
 
80
                                       VMCIPrivilegeFlags *privFlags);
 
81
static void DatagramFreeCB(void *resource);
 
82
static int DatagramReleaseCB(void *clientData);
 
83
 
 
84
static DatagramWKMapping *DatagramGetWellKnownMap(VMCIId wellKnownID);
 
85
static void DatagramReleaseWellKnownMap(DatagramWKMapping *wkMap);
 
86
 
 
87
 
 
88
/*------------------------------ Helper functions ----------------------------*/
 
89
 
 
90
/*
 
91
 *------------------------------------------------------------------------------
 
92
 *
 
93
 *  DatagramFreeCB --
 
94
 *     Callback to free datagram structure when resource is no longer used,
 
95
 *     ie. the reference count reached 0.
 
96
 *
 
97
 *  Result:
 
98
 *     None.
 
99
 *
 
100
 *------------------------------------------------------------------------------
 
101
 */
 
102
 
 
103
static void
 
104
DatagramFreeCB(void *clientData)
 
105
{
 
106
   DatagramEntry *entry = (DatagramEntry *)clientData;
 
107
   ASSERT(entry);
 
108
   VMCI_SignalEvent(&entry->destroyEvent);
 
109
 
 
110
   /*
 
111
    * The entry is freed in VMCIDatagram_DestroyHnd, who is waiting for the
 
112
    * above signal.
 
113
    */
 
114
}
 
115
 
 
116
 
 
117
/*
 
118
 *------------------------------------------------------------------------------
 
119
 *
 
120
 *  DatagramReleaseCB --
 
121
 *
 
122
 *     Callback to release the resource reference. It is called by the
 
123
 *     VMCI_WaitOnEvent function before it blocks.
 
124
 *
 
125
 *  Result:
 
126
 *     None.
 
127
 *
 
128
 *------------------------------------------------------------------------------
 
129
 */
 
130
 
 
131
static int
 
132
DatagramReleaseCB(void *clientData)
 
133
{
 
134
   DatagramEntry *entry = (DatagramEntry *)clientData;
 
135
   ASSERT(entry);
 
136
   VMCIResource_Release(&entry->resource);
 
137
   return 0;
 
138
}
 
139
 
 
140
 
 
141
/*
 
142
 *------------------------------------------------------------------------------
 
143
 *
 
144
 * DatagramCreateHnd --
 
145
 *
 
146
 *      Internal function to create a datagram entry given a handle.
 
147
 *
 
148
 * Results:
 
149
 *      VMCI_SUCCESS if created, negative errno value otherwise.
 
150
 *
 
151
 * Side effects:
 
152
 *      None.
 
153
 *
 
154
 *------------------------------------------------------------------------------
 
155
 */
 
156
 
 
157
static int
 
158
DatagramCreateHnd(VMCIId resourceID,            // IN:
 
159
                  uint32 flags,                 // IN:
 
160
                  VMCIPrivilegeFlags privFlags, // IN:
 
161
                  VMCIDatagramRecvCB recvCB,    // IN:
 
162
                  void *clientData,             // IN:
 
163
                  VMCIHandle *outHandle)        // OUT:
 
164
 
 
165
{
 
166
   int result;
 
167
   VMCIId contextID;
 
168
   VMCIHandle handle;
 
169
   DatagramEntry *entry;
 
170
 
 
171
   ASSERT(recvCB != NULL);
 
172
   ASSERT(outHandle != NULL);
 
173
   ASSERT(!(privFlags & ~VMCI_PRIVILEGE_ALL_FLAGS));
 
174
 
 
175
   if ((flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0) {
 
176
      return VMCI_ERROR_INVALID_ARGS;
 
177
   } else {
 
178
      if ((flags & VMCI_FLAG_ANYCID_DG_HND) != 0) {
 
179
         contextID = VMCI_INVALID_ID;
 
180
      } else {
 
181
         contextID = VMCI_GetContextID();
 
182
         if (contextID == VMCI_INVALID_ID) {
 
183
            return VMCI_ERROR_NO_RESOURCES;
 
184
         }
 
185
      }
 
186
 
 
187
      if (resourceID == VMCI_INVALID_ID) {
 
188
         resourceID = VMCIResource_GetID(contextID);
 
189
         if (resourceID == VMCI_INVALID_ID) {
 
190
            return VMCI_ERROR_NO_HANDLE;
 
191
         }
 
192
      }
 
193
 
 
194
      handle = VMCI_MAKE_HANDLE(contextID, resourceID);
 
195
   }
 
196
 
 
197
   entry = VMCI_AllocKernelMem(sizeof *entry, VMCI_MEMORY_NONPAGED);
 
198
   if (entry == NULL) {
 
199
      VMCI_WARNING((LGPFX"Failed allocating memory for datagram entry.\n"));
 
200
      return VMCI_ERROR_NO_MEM;
 
201
   }
 
202
 
 
203
   if (!VMCI_CanScheduleDelayedWork()) {
 
204
      if (flags & VMCI_FLAG_DG_DELAYED_CB) {
 
205
         VMCI_FreeKernelMem(entry, sizeof *entry);
 
206
         return VMCI_ERROR_INVALID_ARGS;
 
207
      }
 
208
      entry->runDelayed = FALSE;
 
209
   } else {
 
210
      entry->runDelayed = (flags & VMCI_FLAG_DG_DELAYED_CB) ? TRUE : FALSE;
 
211
   }
 
212
 
 
213
   entry->flags = flags;
 
214
   entry->recvCB = recvCB;
 
215
   entry->clientData = clientData;
 
216
   VMCI_CreateEvent(&entry->destroyEvent);
 
217
   entry->privFlags = privFlags;
 
218
 
 
219
   /* Make datagram resource live. */
 
220
   result = VMCIResource_Add(&entry->resource, VMCI_RESOURCE_TYPE_DATAGRAM,
 
221
                             handle, DatagramFreeCB, entry);
 
222
   if (result != VMCI_SUCCESS) {
 
223
      VMCI_WARNING((LGPFX"Failed to add new resource (handle=0x%x:0x%x).\n",
 
224
                    handle.context, handle.resource));
 
225
      VMCI_DestroyEvent(&entry->destroyEvent);
 
226
      VMCI_FreeKernelMem(entry, sizeof *entry);
 
227
      return result;
 
228
   }
 
229
   *outHandle = handle;
 
230
 
 
231
   return VMCI_SUCCESS;
 
232
}
 
233
 
 
234
 
 
235
/*------------------------------ Init functions ----------------------------*/
 
236
 
 
237
/*
 
238
 *------------------------------------------------------------------------------
 
239
 *
 
240
 *  VMCIDatagram_Init --
 
241
 *
 
242
 *     Initialize Datagram API, ie. register the API functions with their
 
243
 *     corresponding vectors.
 
244
 *
 
245
 *  Result:
 
246
 *     None.
 
247
 *
 
248
 * Side effects:
 
249
 *      None.
 
250
 *
 
251
 *------------------------------------------------------------------------------
 
252
 */
 
253
 
 
254
int
 
255
VMCIDatagram_Init(void)
 
256
{
 
257
   /* Create hash table for wellknown mappings. */
 
258
   wellKnownTable = VMCIHashTable_Create(32);
 
259
   if (wellKnownTable == NULL) {
 
260
      return VMCI_ERROR_NO_RESOURCES;
 
261
   }
 
262
 
 
263
   Atomic_Write(&delayedDGHostQueueSize, 0);
 
264
   return VMCI_SUCCESS;
 
265
}
 
266
 
 
267
 
 
268
/*
 
269
 *------------------------------------------------------------------------------
 
270
 *
 
271
 *  VMCIDatagram_Exit --
 
272
 *
 
273
 *     Cleanup Datagram API.
 
274
 *
 
275
 *  Result:
 
276
 *     None.
 
277
 *
 
278
 * Side effects:
 
279
 *      None.
 
280
 *
 
281
 *------------------------------------------------------------------------------
 
282
 */
 
283
 
 
284
void
 
285
VMCIDatagram_Exit(void)
 
286
{
 
287
   if (wellKnownTable != NULL) {
 
288
      VMCIHashTable_Destroy(wellKnownTable);
 
289
      wellKnownTable = NULL;
 
290
   }
 
291
}
 
292
 
 
293
 
 
294
/*------------------------------ Public API functions ------------------------*/
 
295
 
 
296
/*
 
297
 *------------------------------------------------------------------------------
 
298
 *
 
299
 * VMCIDatagram_CreateHnd --
 
300
 *
 
301
 *      Creates a host context datagram endpoint and returns a handle to it.
 
302
 *
 
303
 * Results:
 
304
 *      VMCI_SUCCESS if created, negative errno value otherwise.
 
305
 *
 
306
 * Side effects:
 
307
 *      None.
 
308
 *
 
309
 *------------------------------------------------------------------------------
 
310
 */
 
311
 
 
312
VMCI_EXPORT_SYMBOL(VMCIDatagram_CreateHnd)
 
313
int
 
314
VMCIDatagram_CreateHnd(VMCIId resourceID,          // IN: Optional, generated
 
315
                                                   //     if VMCI_INVALID_ID
 
316
                       uint32 flags,               // IN:
 
317
                       VMCIDatagramRecvCB recvCB,  // IN:
 
318
                       void *clientData,           // IN:
 
319
                       VMCIHandle *outHandle)      // OUT: newly created handle
 
320
{
 
321
   if (outHandle == NULL) {
 
322
      return VMCI_ERROR_INVALID_ARGS;
 
323
   }
 
324
 
 
325
   if (recvCB == NULL) {
 
326
      VMCI_DEBUG_LOG(4,
 
327
                     (LGPFX"Client callback needed when creating datagram.\n"));
 
328
      return VMCI_ERROR_INVALID_ARGS;
 
329
   }
 
330
 
 
331
   return DatagramCreateHnd(resourceID, flags, VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS,
 
332
                            recvCB, clientData, outHandle);
 
333
}
 
334
 
 
335
 
 
336
/*
 
337
 *------------------------------------------------------------------------------
 
338
 *
 
339
 * VMCIDatagram_CreateHndPriv --
 
340
 *
 
341
 *      Creates a host context datagram endpoint and returns a handle to it.
 
342
 *
 
343
 * Results:
 
344
 *      VMCI_SUCCESS if created, negative errno value otherwise.
 
345
 *
 
346
 * Side effects:
 
347
 *      None.
 
348
 *
 
349
 *------------------------------------------------------------------------------
 
350
 */
 
351
 
 
352
VMCI_EXPORT_SYMBOL(VMCIDatagram_CreateHndPriv)
 
353
int
 
354
VMCIDatagram_CreateHndPriv(VMCIId resourceID,           // IN: Optional, generated
 
355
                                                        //     if VMCI_INVALID_ID
 
356
                           uint32 flags,                // IN:
 
357
                           VMCIPrivilegeFlags privFlags,// IN:
 
358
                           VMCIDatagramRecvCB recvCB,   // IN:
 
359
                           void *clientData,            // IN:
 
360
                           VMCIHandle *outHandle)       // OUT: newly created handle
 
361
{
 
362
   if (outHandle == NULL) {
 
363
      return VMCI_ERROR_INVALID_ARGS;
 
364
   }
 
365
 
 
366
   if (recvCB == NULL) {
 
367
      VMCI_DEBUG_LOG(4,
 
368
                     (LGPFX"Client callback needed when creating datagram.\n"));
 
369
      return VMCI_ERROR_INVALID_ARGS;
 
370
   }
 
371
 
 
372
   if (privFlags & ~VMCI_PRIVILEGE_ALL_FLAGS) {
 
373
      return VMCI_ERROR_INVALID_ARGS;
 
374
   }
 
375
 
 
376
   return DatagramCreateHnd(resourceID, flags, privFlags, recvCB, clientData,
 
377
                            outHandle);
 
378
}
 
379
 
 
380
 
 
381
/*
 
382
 *------------------------------------------------------------------------------
 
383
 *
 
384
 * VMCIDatagram_DestroyHnd --
 
385
 *
 
386
 *      Destroys a handle.
 
387
 *
 
388
 * Results:
 
389
 *      None.
 
390
 *
 
391
 * Side effects:
 
392
 *      None.
 
393
 *
 
394
 *------------------------------------------------------------------------------
 
395
 */
 
396
 
 
397
VMCI_EXPORT_SYMBOL(VMCIDatagram_DestroyHnd)
 
398
int
 
399
VMCIDatagram_DestroyHnd(VMCIHandle handle)       // IN
 
400
{
 
401
   DatagramEntry *entry;
 
402
   VMCIResource *resource = VMCIResource_Get(handle,
 
403
                                             VMCI_RESOURCE_TYPE_DATAGRAM);
 
404
   if (resource == NULL) {
 
405
      VMCI_DEBUG_LOG(4, (LGPFX"Failed to destroy datagram (handle=0x%x:0x%x).\n",
 
406
                         handle.context, handle.resource));
 
407
      return VMCI_ERROR_NOT_FOUND;
 
408
   }
 
409
   entry = RESOURCE_CONTAINER(resource, DatagramEntry, resource);
 
410
 
 
411
   VMCIResource_Remove(handle, VMCI_RESOURCE_TYPE_DATAGRAM);
 
412
 
 
413
   /*
 
414
    * We now wait on the destroyEvent and release the reference we got
 
415
    * above.
 
416
    */
 
417
   VMCI_WaitOnEvent(&entry->destroyEvent, DatagramReleaseCB, entry);
 
418
 
 
419
   if ((entry->flags & VMCI_FLAG_WELLKNOWN_DG_HND) != 0) {
 
420
      VMCIDatagramRemoveWellKnownMap(handle.resource, VMCI_HOST_CONTEXT_ID);
 
421
   }
 
422
 
 
423
   /*
 
424
    * We know that we are now the only reference to the above entry so
 
425
     * can safely free it.
 
426
     */
 
427
   VMCI_DestroyEvent(&entry->destroyEvent);
 
428
   VMCI_FreeKernelMem(entry, sizeof *entry);
 
429
 
 
430
   return VMCI_SUCCESS;
 
431
}
 
432
 
 
433
 
 
434
/*
 
435
 *------------------------------------------------------------------------------
 
436
 *
 
437
 *  VMCIDatagramGetPrivFlagsInt --
 
438
 *
 
439
 *     Internal utilility function with the same purpose as
 
440
 *     VMCIDatagram_GetPrivFlags that also takes a contextID.
 
441
 *
 
442
 *  Result:
 
443
 *     VMCI_SUCCESS on success, VMCI_ERROR_INVALID_ARGS if handle is invalid.
 
444
 *
 
445
 *  Side effects:
 
446
 *     None.
 
447
 *
 
448
 *------------------------------------------------------------------------------
 
449
 */
 
450
 
 
451
static int
 
452
VMCIDatagramGetPrivFlagsInt(VMCIId contextID,              // IN
 
453
                            VMCIHandle handle,             // IN
 
454
                            VMCIPrivilegeFlags *privFlags) // OUT
 
455
{
 
456
   ASSERT(privFlags);
 
457
   ASSERT(contextID != VMCI_INVALID_ID);
 
458
 
 
459
   if (contextID == VMCI_HOST_CONTEXT_ID) {
 
460
      DatagramEntry *srcEntry;
 
461
      VMCIResource *resource;
 
462
 
 
463
      resource = VMCIResource_Get(handle, VMCI_RESOURCE_TYPE_DATAGRAM);
 
464
      if (resource == NULL) {
 
465
         return VMCI_ERROR_INVALID_ARGS;
 
466
      }
 
467
      srcEntry = RESOURCE_CONTAINER(resource, DatagramEntry, resource);
 
468
      *privFlags = srcEntry->privFlags;
 
469
      VMCIResource_Release(resource);
 
470
   } else if (contextID == VMCI_HYPERVISOR_CONTEXT_ID) {
 
471
      *privFlags = VMCI_MAX_PRIVILEGE_FLAGS;
 
472
   } else {
 
473
      *privFlags = VMCIContext_GetPrivFlags(contextID);
 
474
   }
 
475
 
 
476
   return VMCI_SUCCESS;
 
477
}
 
478
 
 
479
 
 
480
/*
 
481
 *------------------------------------------------------------------------------
 
482
 *
 
483
 *  VMCIDatagram_GetPrivFlags --
 
484
 *
 
485
 *     Utilility function that retrieves the privilege flags
 
486
 *     associated with a given datagram handle. For hypervisor and
 
487
 *     guest endpoints, the privileges are determined by the context
 
488
 *     ID, but for host endpoints privileges are associated with the
 
489
 *     complete handle.
 
490
 *
 
491
 *  Result:
 
492
 *     VMCI_SUCCESS on success, VMCI_ERROR_INVALID_ARGS if handle is invalid.
 
493
 *
 
494
 *  Side effects:
 
495
 *     None.
 
496
 *
 
497
 *------------------------------------------------------------------------------
 
498
 */
 
499
 
 
500
int
 
501
VMCIDatagram_GetPrivFlags(VMCIHandle handle,             // IN
 
502
                          VMCIPrivilegeFlags *privFlags) // OUT
 
503
{
 
504
   if (privFlags == NULL || handle.context == VMCI_INVALID_ID) {
 
505
      return VMCI_ERROR_INVALID_ARGS;
 
506
   }
 
507
 
 
508
   return VMCIDatagramGetPrivFlagsInt(handle.context, handle, privFlags);
 
509
}
 
510
 
 
511
 
 
512
/*
 
513
 *-----------------------------------------------------------------------------
 
514
 *
 
515
 * VMCIDatagramDelayedDispatchCB --
 
516
 *
 
517
 *      Calls the specified callback in a delayed context.
 
518
 *
 
519
 * Results:
 
520
 *      None.
 
521
 *
 
522
 * Side effects:
 
523
 *      None.
 
524
 *
 
525
 *-----------------------------------------------------------------------------
 
526
 */
 
527
 
 
528
static void
 
529
VMCIDatagramDelayedDispatchCB(void *data) // IN
 
530
{
 
531
   Bool inDGHostQueue;
 
532
   VMCIDelayedDatagramInfo *dgInfo = (VMCIDelayedDatagramInfo *)data;
 
533
 
 
534
   ASSERT(data);
 
535
 
 
536
   dgInfo->entry->recvCB(dgInfo->entry->clientData, &dgInfo->msg);
 
537
 
 
538
   VMCIResource_Release(&dgInfo->entry->resource);
 
539
 
 
540
   inDGHostQueue = dgInfo->inDGHostQueue;
 
541
   VMCI_FreeKernelMem(dgInfo, sizeof *dgInfo + (size_t)dgInfo->msg.payloadSize);
 
542
 
 
543
   if (inDGHostQueue) {
 
544
      Atomic_Dec(&delayedDGHostQueueSize);
 
545
   }
 
546
}
 
547
 
 
548
 
 
549
/*
 
550
 *------------------------------------------------------------------------------
 
551
 *
 
552
 *  VMCIDatagramDispatchAsHost --
 
553
 *
 
554
 *     Dispatch datagram as a host, to the host or other vm context. This
 
555
 *     function cannot dispatch to hypervisor context handlers. This should
 
556
 *     have been handled before we get here by VMCIDatagramDispatch.
 
557
 *
 
558
 *  Result:
 
559
 *     Number of bytes sent on success, appropriate error code otherwise.
 
560
 *
 
561
 *  Side effects:
 
562
 *     None.
 
563
 *
 
564
 *------------------------------------------------------------------------------
 
565
 */
 
566
 
 
567
static int
 
568
VMCIDatagramDispatchAsHost(VMCIId contextID,  // IN:
 
569
                           VMCIDatagram *dg)  // IN:
 
570
{
 
571
   int retval;
 
572
   size_t dgSize;
 
573
   VMCIId dstContext;
 
574
   VMCIPrivilegeFlags srcPrivFlags;
 
575
   char srcDomain[VMCI_DOMAIN_NAME_MAXLEN]; /* Not used on hosted. */
 
576
   char dstDomain[VMCI_DOMAIN_NAME_MAXLEN]; /* Not used on hosted. */
 
577
 
 
578
   ASSERT(dg);
 
579
   ASSERT(VMCI_HostPersonalityActive());
 
580
 
 
581
   dgSize = VMCI_DG_SIZE(dg);
 
582
 
 
583
   if (contextID == VMCI_HOST_CONTEXT_ID &&
 
584
       dg->dst.context == VMCI_HYPERVISOR_CONTEXT_ID) {
 
585
      return VMCI_ERROR_DST_UNREACHABLE;
 
586
   }
 
587
 
 
588
   ASSERT(dg->dst.context != VMCI_HYPERVISOR_CONTEXT_ID);
 
589
 
 
590
   /* Chatty. */
 
591
   // VMCI_DEBUG_LOG(10, (LGPFX"Sending from (handle=0x%x:0x%x) to "
 
592
   //                     "(handle=0x%x:0x%x) (size=%u bytes).\n",
 
593
   //                     dg->src.context, dg->src.resource,
 
594
   //                     dg->dst.context, dg->dst.resource, (uint32)dgSize));
 
595
 
 
596
   /*
 
597
    * Check that source handle matches sending context.
 
598
    */
 
599
   if (dg->src.context != contextID) {
 
600
      if (dg->src.context == VMCI_WELL_KNOWN_CONTEXT_ID) {
 
601
         /* Determine mapping. */
 
602
         DatagramWKMapping *wkMap = DatagramGetWellKnownMap(dg->src.resource);
 
603
         if (wkMap == NULL) {
 
604
            VMCI_DEBUG_LOG(4, (LGPFX"Sending from invalid well-known resource "
 
605
                               "(handle=0x%x:0x%x).\n",
 
606
                               dg->src.context, dg->src.resource));
 
607
            return VMCI_ERROR_INVALID_RESOURCE;
 
608
         }
 
609
         if (wkMap->contextID != contextID) {
 
610
            VMCI_DEBUG_LOG(4, (LGPFX"Sender context (ID=0x%x) is not owner of "
 
611
                               "well-known src datagram entry "
 
612
                               "(handle=0x%x:0x%x).\n",
 
613
                               contextID, dg->src.context, dg->src.resource));
 
614
            DatagramReleaseWellKnownMap(wkMap);
 
615
            return VMCI_ERROR_NO_ACCESS;
 
616
         }
 
617
         DatagramReleaseWellKnownMap(wkMap);
 
618
      } else {
 
619
         VMCI_DEBUG_LOG(4, (LGPFX"Sender context (ID=0x%x) is not owner of src "
 
620
                            "datagram entry (handle=0x%x:0x%x).\n",
 
621
                            contextID, dg->src.context, dg->src.resource));
 
622
         return VMCI_ERROR_NO_ACCESS;
 
623
      }
 
624
   }
 
625
 
 
626
   if (dg->dst.context == VMCI_WELL_KNOWN_CONTEXT_ID) {
 
627
      /* Determine mapping. */
 
628
      DatagramWKMapping *wkMap = DatagramGetWellKnownMap(dg->dst.resource);
 
629
      if (wkMap == NULL) {
 
630
         VMCI_DEBUG_LOG(4, (LGPFX"Sending to invalid wellknown destination "
 
631
                            "(handle=0x%x:0x%x).\n",
 
632
                            dg->dst.context, dg->dst.resource));
 
633
         return VMCI_ERROR_DST_UNREACHABLE;
 
634
      }
 
635
      dstContext = wkMap->contextID;
 
636
      DatagramReleaseWellKnownMap(wkMap);
 
637
   } else {
 
638
      dstContext = dg->dst.context;
 
639
   }
 
640
 
 
641
   /*
 
642
    * Get hold of privileges of sending endpoint.
 
643
    */
 
644
 
 
645
   retval = VMCIDatagramGetPrivFlagsInt(contextID, dg->src, &srcPrivFlags);
 
646
   if (retval != VMCI_SUCCESS) {
 
647
      VMCI_WARNING((LGPFX"Couldn't get privileges (handle=0x%x:0x%x).\n",
 
648
                    dg->src.context, dg->src.resource));
 
649
      return retval;
 
650
   }
 
651
 
 
652
#ifdef VMKERNEL
 
653
   /*
 
654
    * In the vmkernel, all communicating contexts except the
 
655
    * hypervisor context must belong to the same domain. If the
 
656
    * hypervisor is the source, the domain doesn't matter.
 
657
    */
 
658
 
 
659
   if (contextID != VMCI_HYPERVISOR_CONTEXT_ID) {
 
660
      retval = VMCIContext_GetDomainName(contextID, srcDomain,
 
661
                                         sizeof srcDomain);
 
662
      if (retval < VMCI_SUCCESS) {
 
663
         VMCI_WARNING((LGPFX"Failed to get domain name for context (ID=0x%x).\n",
 
664
                       contextID));
 
665
         return retval;
 
666
      }
 
667
   }
 
668
#endif
 
669
 
 
670
   /* Determine if we should route to host or guest destination. */
 
671
   if (dstContext == VMCI_HOST_CONTEXT_ID) {
 
672
      /* Route to host datagram entry. */
 
673
      DatagramEntry *dstEntry;
 
674
      VMCIResource *resource;
 
675
 
 
676
      if (dg->src.context == VMCI_HYPERVISOR_CONTEXT_ID &&
 
677
          dg->dst.resource == VMCI_EVENT_HANDLER) {
 
678
         return VMCIEvent_Dispatch(dg);
 
679
      }
 
680
 
 
681
      resource = VMCIResource_Get(dg->dst, VMCI_RESOURCE_TYPE_DATAGRAM);
 
682
      if (resource == NULL) {
 
683
         VMCI_DEBUG_LOG(4, (LGPFX"Sending to invalid destination "
 
684
                            "(handle=0x%x:0x%x).\n",
 
685
                            dg->dst.context, dg->dst.resource));
 
686
         return VMCI_ERROR_INVALID_RESOURCE;
 
687
      }
 
688
      dstEntry = RESOURCE_CONTAINER(resource, DatagramEntry, resource);
 
689
#ifdef VMKERNEL
 
690
      retval = VMCIContext_GetDomainName(VMCI_HOST_CONTEXT_ID, dstDomain,
 
691
                                         sizeof dstDomain);
 
692
      if (retval < VMCI_SUCCESS) {
 
693
         VMCI_WARNING((LGPFX"Failed to get domain name for context (ID=0x%x).\n",
 
694
                       VMCI_HOST_CONTEXT_ID));
 
695
         VMCIResource_Release(resource);
 
696
         return retval;
 
697
      }
 
698
#endif
 
699
      if (VMCIDenyInteraction(srcPrivFlags, dstEntry->privFlags, srcDomain,
 
700
                              dstDomain)) {
 
701
         VMCIResource_Release(resource);
 
702
         return VMCI_ERROR_NO_ACCESS;
 
703
      }
 
704
      ASSERT(dstEntry->recvCB);
 
705
 
 
706
      /*
 
707
       * If a VMCI datagram destined for the host is also sent by the
 
708
       * host, we always run it delayed. This ensures that no locks
 
709
       * are held when the datagram callback runs.
 
710
       */
 
711
 
 
712
      if (dstEntry->runDelayed ||
 
713
          (dg->src.context == VMCI_HOST_CONTEXT_ID &&
 
714
           VMCI_CanScheduleDelayedWork())) {
 
715
         VMCIDelayedDatagramInfo *dgInfo;
 
716
 
 
717
         if (Atomic_FetchAndAdd(&delayedDGHostQueueSize, 1) ==
 
718
             VMCI_MAX_DELAYED_DG_HOST_QUEUE_SIZE) {
 
719
            Atomic_Dec(&delayedDGHostQueueSize);
 
720
            VMCIResource_Release(resource);
 
721
            return VMCI_ERROR_NO_MEM;
 
722
         }
 
723
 
 
724
         dgInfo = VMCI_AllocKernelMem(sizeof *dgInfo + (size_t)dg->payloadSize,
 
725
                                      (VMCI_MEMORY_ATOMIC |
 
726
                                       VMCI_MEMORY_NONPAGED));
 
727
         if (NULL == dgInfo) {
 
728
            Atomic_Dec(&delayedDGHostQueueSize);
 
729
            VMCIResource_Release(resource);
 
730
            return VMCI_ERROR_NO_MEM;
 
731
         }
 
732
 
 
733
         dgInfo->inDGHostQueue = TRUE;
 
734
         dgInfo->entry = dstEntry;
 
735
         memcpy(&dgInfo->msg, dg, dgSize);
 
736
 
 
737
         retval = VMCI_ScheduleDelayedWork(VMCIDatagramDelayedDispatchCB, dgInfo);
 
738
         if (retval < VMCI_SUCCESS) {
 
739
            VMCI_WARNING((LGPFX"Failed to schedule delayed work for datagram "
 
740
                          "(result=%d).\n", retval));
 
741
            VMCI_FreeKernelMem(dgInfo, sizeof *dgInfo + (size_t)dg->payloadSize);
 
742
            VMCIResource_Release(resource);
 
743
            Atomic_Dec(&delayedDGHostQueueSize);
 
744
            return retval;
 
745
         }
 
746
      } else {
 
747
         retval = dstEntry->recvCB(dstEntry->clientData, dg);
 
748
         VMCIResource_Release(resource);
 
749
         if (retval < VMCI_SUCCESS) {
 
750
            return retval;
 
751
         }
 
752
      }
 
753
   } else {
 
754
      /* Route to destination VM context. */
 
755
      VMCIDatagram *newDG;
 
756
 
 
757
#ifdef VMKERNEL
 
758
      retval = VMCIContext_GetDomainName(dstContext, dstDomain,
 
759
                                         sizeof dstDomain);
 
760
      if (retval < VMCI_SUCCESS) {
 
761
         VMCI_DEBUG_LOG(4, (LGPFX"Failed to get domain name for context "
 
762
                            "(ID=0x%x).\n", dstContext));
 
763
         return retval;
 
764
      }
 
765
#endif
 
766
      if (contextID != dstContext &&
 
767
         VMCIDenyInteraction(srcPrivFlags, VMCIContext_GetPrivFlags(dstContext),
 
768
                             srcDomain, dstDomain)) {
 
769
         return VMCI_ERROR_NO_ACCESS;
 
770
      }
 
771
 
 
772
      /* We make a copy to enqueue. */
 
773
      newDG = VMCI_AllocKernelMem(dgSize, VMCI_MEMORY_NORMAL);
 
774
      if (newDG == NULL) {
 
775
         return VMCI_ERROR_NO_MEM;
 
776
      }
 
777
      memcpy(newDG, dg, dgSize);
 
778
      retval = VMCIContext_EnqueueDatagram(dstContext, newDG);
 
779
      if (retval < VMCI_SUCCESS) {
 
780
         VMCI_FreeKernelMem(newDG, dgSize);
 
781
         return retval;
 
782
      }
 
783
   }
 
784
 
 
785
   /* The datagram is freed when the context reads it. */
 
786
 
 
787
   /* Chatty. */
 
788
   // VMCI_DEBUG_LOG(10, (LGPFX"Sent datagram (size=%u bytes).\n",
 
789
   //                     (uint32)dgSize));
 
790
 
 
791
   /*
 
792
    * We currently truncate the size to signed 32 bits. This doesn't
 
793
    * matter for this handler as it only support 4Kb messages.
 
794
    */
 
795
 
 
796
   return (int)dgSize;
 
797
}
 
798
 
 
799
 
 
800
/*
 
801
 *------------------------------------------------------------------------------
 
802
 *
 
803
 *  VMCIDatagramDispatchAsGuest --
 
804
 *
 
805
 *     Dispatch datagram as a guest, down through the VMX and potentially to
 
806
 *     the host.
 
807
 *
 
808
 *  Result:
 
809
 *     Number of bytes sent on success, appropriate error code otherwise.
 
810
 *
 
811
 *  Side effects:
 
812
 *     None.
 
813
 *
 
814
 *------------------------------------------------------------------------------
 
815
 */
 
816
 
 
817
static int
 
818
VMCIDatagramDispatchAsGuest(VMCIDatagram *dg)
 
819
{
 
820
#if defined(VMKERNEL)
 
821
   VMCI_WARNING((LGPFX"Cannot send down to host from VMKERNEL.\n"));
 
822
   return VMCI_ERROR_DST_UNREACHABLE;
 
823
#else // VMKERNEL
 
824
   int retval;
 
825
   VMCIResource *resource;
 
826
 
 
827
   ASSERT(VMCI_GuestPersonalityActive());
 
828
 
 
829
   resource = VMCIResource_Get(dg->src, VMCI_RESOURCE_TYPE_DATAGRAM);
 
830
   if (NULL == resource) {
 
831
      return VMCI_ERROR_NO_HANDLE;
 
832
   }
 
833
 
 
834
   retval = VMCI_SendDatagram(dg);
 
835
   VMCIResource_Release(resource);
 
836
   return retval;
 
837
#endif // VMKERNEL
 
838
}
 
839
 
 
840
 
 
841
 
 
842
/*
 
843
 *------------------------------------------------------------------------------
 
844
 *
 
845
 *  VMCIDatagram_Dispatch --
 
846
 *
 
847
 *     Dispatch datagram.  This will determine the routing for the datagram
 
848
 *     and dispatch it accordingly.
 
849
 *
 
850
 *  Result:
 
851
 *     Number of bytes sent on success, appropriate error code otherwise.
 
852
 *
 
853
 *  Side effects:
 
854
 *     None.
 
855
 *
 
856
 *------------------------------------------------------------------------------
 
857
 */
 
858
 
 
859
int
 
860
VMCIDatagram_Dispatch(VMCIId contextID,
 
861
                      VMCIDatagram *dg,
 
862
                      Bool fromGuest)
 
863
{
 
864
   int retval;
 
865
   VMCIRoute route;
 
866
 
 
867
   ASSERT(dg);
 
868
   ASSERT_ON_COMPILE(sizeof(VMCIDatagram) == 24);
 
869
 
 
870
   if (VMCI_DG_SIZE(dg) > VMCI_MAX_DG_SIZE) {
 
871
      VMCI_DEBUG_LOG(4, (LGPFX"Payload (size=%"FMT64"u bytes) too big to "
 
872
                         "send.\n", dg->payloadSize));
 
873
      return VMCI_ERROR_INVALID_ARGS;
 
874
   }
 
875
 
 
876
   retval = VMCI_Route(&dg->src, &dg->dst, fromGuest, &route);
 
877
   if (retval < VMCI_SUCCESS) {
 
878
      return retval;
 
879
   }
 
880
 
 
881
   if (VMCI_ROUTE_AS_HOST == route) {
 
882
      if (VMCI_INVALID_ID == contextID) {
 
883
         contextID = VMCI_HOST_CONTEXT_ID;
 
884
      }
 
885
      return VMCIDatagramDispatchAsHost(contextID, dg);
 
886
   }
 
887
 
 
888
   if (VMCI_ROUTE_AS_GUEST == route) {
 
889
      return VMCIDatagramDispatchAsGuest(dg);
 
890
   }
 
891
 
 
892
   VMCI_WARNING((LGPFX"Unknown route (%d) for datagram.\n", route));
 
893
   return VMCI_ERROR_DST_UNREACHABLE;
 
894
}
 
895
 
 
896
 
 
897
/*
 
898
 *------------------------------------------------------------------------------
 
899
 *
 
900
 *  VMCIDatagram_InvokeGuestHandler --
 
901
 *
 
902
 *     Invoke the handler for the given datagram.  This is intended to be
 
903
 *     called only when acting as a guest and receiving a datagram from the
 
904
 *     virtual device.
 
905
 *
 
906
 *  Result:
 
907
 *     VMCI_SUCCESS on success, other error values on failure.
 
908
 *
 
909
 *  Side effects:
 
910
 *     None.
 
911
 *
 
912
 *------------------------------------------------------------------------------
 
913
 */
 
914
 
 
915
int
 
916
VMCIDatagram_InvokeGuestHandler(VMCIDatagram *dg) // IN
 
917
{
 
918
#if defined(VMKERNEL)
 
919
   VMCI_WARNING((LGPFX"Cannot dispatch within guest in VMKERNEL.\n"));
 
920
   return VMCI_ERROR_DST_UNREACHABLE;
 
921
#else // VMKERNEL
 
922
   int retval;
 
923
   VMCIResource *resource;
 
924
   DatagramEntry *dstEntry;
 
925
 
 
926
   ASSERT(dg);
 
927
   ASSERT(VMCI_GuestPersonalityActive());
 
928
 
 
929
   resource = VMCIResource_Get(dg->dst, VMCI_RESOURCE_TYPE_DATAGRAM);
 
930
   if (NULL == resource) {
 
931
      VMCI_DEBUG_LOG(4, (LGPFX"destination (handle=0x%x:0x%x) doesn't exist.\n",
 
932
                         dg->dst.context, dg->dst.resource));
 
933
      return VMCI_ERROR_NO_HANDLE;
 
934
   }
 
935
 
 
936
   dstEntry = RESOURCE_CONTAINER(resource, DatagramEntry, resource);
 
937
   if (dstEntry->runDelayed) {
 
938
      VMCIDelayedDatagramInfo *dgInfo;
 
939
 
 
940
      dgInfo = VMCI_AllocKernelMem(sizeof *dgInfo + (size_t)dg->payloadSize,
 
941
                                   (VMCI_MEMORY_ATOMIC | VMCI_MEMORY_NONPAGED));
 
942
      if (NULL == dgInfo) {
 
943
         VMCIResource_Release(resource);
 
944
         retval = VMCI_ERROR_NO_MEM;
 
945
         goto exit;
 
946
      }
 
947
 
 
948
      dgInfo->inDGHostQueue = FALSE;
 
949
      dgInfo->entry = dstEntry;
 
950
      memcpy(&dgInfo->msg, dg, VMCI_DG_SIZE(dg));
 
951
 
 
952
      retval = VMCI_ScheduleDelayedWork(VMCIDatagramDelayedDispatchCB, dgInfo);
 
953
      if (retval < VMCI_SUCCESS) {
 
954
         VMCI_WARNING((LGPFX"Failed to schedule delayed work for datagram "
 
955
                       "(result=%d).\n", retval));
 
956
         VMCI_FreeKernelMem(dgInfo, sizeof *dgInfo + (size_t)dg->payloadSize);
 
957
         VMCIResource_Release(resource);
 
958
         dgInfo = NULL;
 
959
         goto exit;
 
960
      }
 
961
   } else {
 
962
      dstEntry->recvCB(dstEntry->clientData, dg);
 
963
      VMCIResource_Release(resource);
 
964
      retval = VMCI_SUCCESS;
 
965
   }
 
966
 
 
967
exit:
 
968
   return retval;
 
969
#endif // VMKERNEL
 
970
}
 
971
 
 
972
 
 
973
/*
 
974
 *------------------------------------------------------------------------------
 
975
 *
 
976
 * VMCIDatagram_Send --
 
977
 *
 
978
 *      Sends the payload to the destination datagram handle.
 
979
 *
 
980
 * Results:
 
981
 *      Returns number of bytes sent if success, or error code if failure.
 
982
 *
 
983
 * Side effects:
 
984
 *      None.
 
985
 *
 
986
 *------------------------------------------------------------------------------
 
987
 */
 
988
 
 
989
VMCI_EXPORT_SYMBOL(VMCIDatagram_Send)
 
990
int
 
991
VMCIDatagram_Send(VMCIDatagram *msg) // IN
 
992
{
 
993
   if (msg == NULL) {
 
994
      return VMCI_ERROR_INVALID_ARGS;
 
995
   }
 
996
 
 
997
   return VMCIDatagram_Dispatch(VMCI_INVALID_ID, msg, FALSE);
 
998
}
 
999
 
 
1000
 
 
1001
/*
 
1002
 *------------------------------------------------------------------------------
 
1003
 *
 
1004
 * DatagramGetWellKnownMap --
 
1005
 *
 
1006
 *      Gets a mapping between handle and wellknown resource.
 
1007
 *
 
1008
 * Results:
 
1009
 *      DatagramWKMapping * if found, NULL if not.
 
1010
 *
 
1011
 * Side effects:
 
1012
 *      None.
 
1013
 *
 
1014
 *------------------------------------------------------------------------------
 
1015
 */
 
1016
 
 
1017
static DatagramWKMapping *
 
1018
DatagramGetWellKnownMap(VMCIId wellKnownID)  // IN:
 
1019
{
 
1020
   VMCIHashEntry *entry;
 
1021
   DatagramWKMapping *wkMap = NULL;
 
1022
   VMCIHandle wkHandle = VMCI_MAKE_HANDLE(VMCI_WELL_KNOWN_CONTEXT_ID,
 
1023
                                          wellKnownID);
 
1024
   entry = VMCIHashTable_GetEntry(wellKnownTable, wkHandle);
 
1025
   if (entry != NULL) {
 
1026
      wkMap = RESOURCE_CONTAINER(entry, DatagramWKMapping, entry);
 
1027
   }
 
1028
   return wkMap;
 
1029
}
 
1030
 
 
1031
 
 
1032
/*
 
1033
 *------------------------------------------------------------------------------
 
1034
 *
 
1035
 * DatagramReleaseWellKnownMap --
 
1036
 *
 
1037
 *      Releases a wellknown mapping.
 
1038
 *
 
1039
 * Results:
 
1040
 *      None.
 
1041
 *
 
1042
 * Side effects:
 
1043
 *      None.
 
1044
 *
 
1045
 *------------------------------------------------------------------------------
 
1046
 */
 
1047
 
 
1048
static void
 
1049
DatagramReleaseWellKnownMap(DatagramWKMapping *wkMap)  // IN:
 
1050
{
 
1051
   if (VMCIHashTable_ReleaseEntry(wellKnownTable, &wkMap->entry) ==
 
1052
       VMCI_SUCCESS_ENTRY_DEAD) {
 
1053
      VMCI_FreeKernelMem(wkMap, sizeof *wkMap);
 
1054
   }
 
1055
}
 
1056
 
 
1057
 
 
1058
/*
 
1059
 *------------------------------------------------------------------------------
 
1060
 *
 
1061
 * VMCIDatagramRequestWellKnownMap --
 
1062
 *
 
1063
 *      Creates a mapping between handle and wellknown resource. If resource
 
1064
 *      is already used we fail the request.
 
1065
 *
 
1066
 * Results:
 
1067
 *      VMCI_SUCCESS if created, negative errno value otherwise.
 
1068
 *
 
1069
 * Side effects:
 
1070
 *      None.
 
1071
 *
 
1072
 *------------------------------------------------------------------------------
 
1073
 */
 
1074
 
 
1075
int
 
1076
VMCIDatagramRequestWellKnownMap(VMCIId wellKnownID,           // IN:
 
1077
                                VMCIId contextID,             // IN:
 
1078
                                VMCIPrivilegeFlags privFlags) // IN:
 
1079
{
 
1080
   int result;
 
1081
   DatagramWKMapping *wkMap;
 
1082
   VMCIHandle wkHandle = VMCI_MAKE_HANDLE(VMCI_WELL_KNOWN_CONTEXT_ID,
 
1083
                                          wellKnownID);
 
1084
 
 
1085
   if (privFlags & VMCI_PRIVILEGE_FLAG_RESTRICTED ||
 
1086
       !VMCIWellKnownID_AllowMap(wellKnownID, privFlags)) {
 
1087
      return VMCI_ERROR_NO_ACCESS;
 
1088
   }
 
1089
 
 
1090
   wkMap = VMCI_AllocKernelMem(sizeof *wkMap, VMCI_MEMORY_NONPAGED);
 
1091
   if (wkMap == NULL) {
 
1092
      return VMCI_ERROR_NO_MEM;
 
1093
   }
 
1094
 
 
1095
   VMCIHashTable_InitEntry(&wkMap->entry, wkHandle);
 
1096
   wkMap->contextID = contextID;
 
1097
 
 
1098
   /* Fails if wkHandle (wellKnownID) already exists. */
 
1099
   result = VMCIHashTable_AddEntry(wellKnownTable, &wkMap->entry);
 
1100
   if (result != VMCI_SUCCESS) {
 
1101
      VMCI_FreeKernelMem(wkMap, sizeof *wkMap);
 
1102
      return result;
 
1103
   }
 
1104
   result = VMCIContext_AddWellKnown(contextID, wellKnownID);
 
1105
   if (UNLIKELY(result < VMCI_SUCCESS)) {
 
1106
      VMCIHashTable_RemoveEntry(wellKnownTable, &wkMap->entry);
 
1107
      VMCI_FreeKernelMem(wkMap, sizeof *wkMap);
 
1108
   }
 
1109
   return result;
 
1110
}
 
1111
 
 
1112
 
 
1113
/*
 
1114
 *------------------------------------------------------------------------------
 
1115
 *
 
1116
 * VMCIDatagramRemoveWellKnownMap --
 
1117
 *
 
1118
 *      Removes a mapping between handle and wellknown resource. Checks if
 
1119
 *      mapping belongs to calling context.
 
1120
 *
 
1121
 * Results:
 
1122
 *      VMCI_SUCCESS if removed, negative errno value otherwise.
 
1123
 *
 
1124
 * Side effects:
 
1125
 *      None.
 
1126
 *
 
1127
 *------------------------------------------------------------------------------
 
1128
 */
 
1129
 
 
1130
int
 
1131
VMCIDatagramRemoveWellKnownMap(VMCIId wellKnownID,  // IN:
 
1132
                               VMCIId contextID)    // IN:
 
1133
{
 
1134
   int result = VMCI_ERROR_NO_ACCESS;
 
1135
   DatagramWKMapping *wkMap = DatagramGetWellKnownMap(wellKnownID);
 
1136
   if (wkMap == NULL) {
 
1137
      VMCI_DEBUG_LOG(4, (LGPFX"Failed to remove well-known mapping between "
 
1138
                         "resource (ID=0x%x) and context (ID=0x%x).\n",
 
1139
                         wellKnownID, contextID));
 
1140
      return VMCI_ERROR_NOT_FOUND;
 
1141
   }
 
1142
 
 
1143
   if (contextID == wkMap->contextID) {
 
1144
      VMCIHashTable_RemoveEntry(wellKnownTable, &wkMap->entry);
 
1145
      VMCIContext_RemoveWellKnown(contextID, wellKnownID);
 
1146
      result = VMCI_SUCCESS;
 
1147
   }
 
1148
   DatagramReleaseWellKnownMap(wkMap);
 
1149
   return result;
 
1150
}
 
1151
 
 
1152
 
 
1153
/*
 
1154
 *-----------------------------------------------------------------------------
 
1155
 *
 
1156
 * VMCIDatagram_Sync --
 
1157
 *
 
1158
 *      Use this as a synchronization point when setting globals, for example,
 
1159
 *      during device shutdown.
 
1160
 *
 
1161
 * Results:
 
1162
 *      None.
 
1163
 *
 
1164
 * Side effects:
 
1165
 *      None.
 
1166
 *
 
1167
 *-----------------------------------------------------------------------------
 
1168
 */
 
1169
 
 
1170
void
 
1171
VMCIDatagram_Sync(void)
 
1172
{
 
1173
   VMCIResource_Sync();
 
1174
}
 
1175
 
 
1176
 
 
1177
/*
 
1178
 *-----------------------------------------------------------------------------
 
1179
 *
 
1180
 * VMCIDatagram_CheckHostCapabilities --
 
1181
 *
 
1182
 *      Verify that the host supports the resources we need.
 
1183
 *      None are required for datagrams since they are implicitly supported.
 
1184
 *
 
1185
 * Results:
 
1186
 *      TRUE.
 
1187
 *
 
1188
 * Side effects:
 
1189
 *      None.
 
1190
 *
 
1191
 *-----------------------------------------------------------------------------
 
1192
 */
 
1193
 
 
1194
Bool
 
1195
VMCIDatagram_CheckHostCapabilities(void)
 
1196
{
 
1197
   return TRUE;
 
1198
}