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

« back to all changes in this revision

Viewing changes to modules/linux/vmci/common/vmciRoute.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) 2011 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
 * vmciRoute.c --
 
21
 *
 
22
 *     Implementation of VMCI routing rules.
 
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 "vmciDriver.h"
 
32
#include "vmciKernelAPI.h"
 
33
#include "vmciRoute.h"
 
34
#if defined(VMKERNEL)
 
35
#  include "vmciVmkInt.h"
 
36
#  include "vm_libc.h"
 
37
#  include "helper_ext.h"
 
38
#endif
 
39
 
 
40
#define LGPFX "VMCIRoute: "
 
41
 
 
42
 
 
43
/*
 
44
 *------------------------------------------------------------------------------
 
45
 *
 
46
 *  VMCI_Route --
 
47
 *
 
48
 *     Make a routing decision for the given source and destination handles.
 
49
 *     This will try to determine the route using the handles and the available
 
50
 *     devices.
 
51
 *
 
52
 *  Result:
 
53
 *     A VMCIRoute value.
 
54
 *
 
55
 *  Side effects:
 
56
 *     Sets the source context if it is invalid.
 
57
 *
 
58
 *------------------------------------------------------------------------------
 
59
 */
 
60
 
 
61
int
 
62
VMCI_Route(VMCIHandle *src,       // IN/OUT
 
63
           const VMCIHandle *dst, // IN
 
64
           Bool fromGuest,        // IN
 
65
           VMCIRoute *route)      // OUT
 
66
{
 
67
   Bool hasHostDevice;
 
68
   Bool hasGuestDevice;
 
69
 
 
70
   ASSERT(src);
 
71
   ASSERT(dst);
 
72
   ASSERT(route);
 
73
 
 
74
   *route = VMCI_ROUTE_NONE;
 
75
 
 
76
   /*
 
77
    * "fromGuest" is only ever set to TRUE by IOCTL_VMCI_DATAGRAM_SEND (or by
 
78
    * the vmkernel equivalent), which comes from the VMX, so we know it is
 
79
    * coming from a guest.
 
80
    */
 
81
 
 
82
   /*
 
83
    * To avoid inconsistencies, test these once.  We will test them again
 
84
    * when we do the actual send to ensure that we do not touch a non-existent
 
85
    * device.
 
86
    */
 
87
 
 
88
   hasHostDevice = VMCI_HostPersonalityActive();
 
89
   hasGuestDevice = VMCI_GuestPersonalityActive();
 
90
 
 
91
   /* Must have a valid destination context. */
 
92
   if (VMCI_INVALID_ID == dst->context) {
 
93
      return VMCI_ERROR_INVALID_ARGS;
 
94
   }
 
95
 
 
96
   /*
 
97
    * If we are acting as a host and the datagram is from or for a well-known
 
98
    * context (which also means it must have been passed down from a guest),
 
99
    * then we can assume it is intended for a guest on this host.
 
100
    */
 
101
 
 
102
   if (fromGuest && hasHostDevice &&
 
103
       (VMCI_WELL_KNOWN_CONTEXT_ID == src->context ||
 
104
        VMCI_WELL_KNOWN_CONTEXT_ID == dst->context)) {
 
105
      *route = VMCI_ROUTE_AS_HOST;
 
106
      return VMCI_SUCCESS;
 
107
   }
 
108
 
 
109
   /* Anywhere to hypervisor. */
 
110
   if (VMCI_HYPERVISOR_CONTEXT_ID == dst->context) {
 
111
      /*
 
112
       * If this message already came from a guest then we cannot send it
 
113
       * to the hypervisor.  It must come from a local client.
 
114
       */
 
115
 
 
116
      if (fromGuest) {
 
117
         return VMCI_ERROR_DST_UNREACHABLE;
 
118
      }
 
119
 
 
120
      /* We must be acting as a guest in order to send to the hypervisor. */
 
121
      if (!hasGuestDevice) {
 
122
         return VMCI_ERROR_DEVICE_NOT_FOUND;
 
123
      }
 
124
 
 
125
      /* And we cannot send if the source is the host context. */
 
126
      if (VMCI_HOST_CONTEXT_ID == src->context) {
 
127
         return VMCI_ERROR_INVALID_ARGS;
 
128
      }
 
129
 
 
130
      /* Send from local client down to the hypervisor. */
 
131
      *route = VMCI_ROUTE_AS_GUEST;
 
132
      return VMCI_SUCCESS;
 
133
   }
 
134
 
 
135
   /* Anywhere to local client on host. */
 
136
   if (VMCI_HOST_CONTEXT_ID == dst->context) {
 
137
      /*
 
138
       * If it is not from a guest but we are acting as a guest, then we need
 
139
       * to send it down to the host.  Note that if we are also acting as a
 
140
       * host then this will prevent us from sending from local client to
 
141
       * local client, but we accept that restriction as a way to remove
 
142
       * any ambiguity from the host context.
 
143
       */
 
144
 
 
145
      if (src->context == VMCI_HYPERVISOR_CONTEXT_ID) {
 
146
         /*
 
147
          * If the hypervisor is the source, this is host local
 
148
          * communication. The hypervisor may send vmci event
 
149
          * datagrams to the host itself, but it will never send
 
150
          * datagrams to an "outer host" through the guest device.
 
151
          */
 
152
 
 
153
         if (hasHostDevice) {
 
154
            *route = VMCI_ROUTE_AS_HOST;
 
155
            return VMCI_SUCCESS;
 
156
         } else {
 
157
            return VMCI_ERROR_DEVICE_NOT_FOUND;
 
158
         }
 
159
      }
 
160
 
 
161
      if (!fromGuest && hasGuestDevice) {
 
162
         /* If no source context then use the current. */
 
163
         if (VMCI_INVALID_ID == src->context) {
 
164
            src->context = VMCI_GetContextID();
 
165
         }
 
166
 
 
167
         /* Send it from local client down to the host. */
 
168
         *route = VMCI_ROUTE_AS_GUEST;
 
169
         return VMCI_SUCCESS;
 
170
      }
 
171
 
 
172
      /*
 
173
       * Otherwise we already received it from a guest and it is destined
 
174
       * for a local client on this host, or it is from another local client
 
175
       * on this host.  We must be acting as a host to service it.
 
176
       */
 
177
 
 
178
      if (!hasHostDevice) {
 
179
         return VMCI_ERROR_DEVICE_NOT_FOUND;
 
180
      }
 
181
 
 
182
      if (VMCI_INVALID_ID == src->context) {
 
183
         /*
 
184
          * If it came from a guest then it must have a valid context.
 
185
          * Otherwise we can use the host context.
 
186
          */
 
187
 
 
188
         if (fromGuest) {
 
189
            return VMCI_ERROR_INVALID_ARGS;
 
190
         }
 
191
         src->context = VMCI_HOST_CONTEXT_ID;
 
192
      }
 
193
 
 
194
      /* Route to local client. */
 
195
      *route = VMCI_ROUTE_AS_HOST;
 
196
      return VMCI_SUCCESS;
 
197
   }
 
198
 
 
199
   /* If we are acting as a host then this might be destined for a guest. */
 
200
   if (hasHostDevice) {
 
201
      /* It will have a context if it is meant for a guest. */
 
202
      if (VMCIContext_Exists(dst->context)) {
 
203
         if (VMCI_INVALID_ID == src->context) {
 
204
            /*
 
205
             * If it came from a guest then it must have a valid context.
 
206
             * Otherwise we can use the host context.
 
207
             */
 
208
 
 
209
            if (fromGuest) {
 
210
               return VMCI_ERROR_INVALID_ARGS;
 
211
            }
 
212
            src->context = VMCI_HOST_CONTEXT_ID;
 
213
         }
 
214
 
 
215
         /* Pass it up to the guest. */
 
216
         *route = VMCI_ROUTE_AS_HOST;
 
217
         return VMCI_SUCCESS;
 
218
      }
 
219
   }
 
220
 
 
221
   /*
 
222
    * We must be a guest trying to send to another guest, which means we
 
223
    * need to send it down to the host.
 
224
    */
 
225
 
 
226
   if (!hasGuestDevice) {
 
227
      return VMCI_ERROR_DEVICE_NOT_FOUND;
 
228
   }
 
229
 
 
230
   /* If no source context then use the current context. */
 
231
   if (VMCI_INVALID_ID == src->context) {
 
232
      src->context = VMCI_GetContextID();
 
233
   }
 
234
 
 
235
   /*
 
236
    * Send it from local client down to the host, which will route it to
 
237
    * the other guest for us.
 
238
    */
 
239
 
 
240
   *route = VMCI_ROUTE_AS_GUEST;
 
241
   return VMCI_SUCCESS;
 
242
}
 
243
 
 
244
 
 
245
/*
 
246
 *------------------------------------------------------------------------------
 
247
 *
 
248
 *  VMCI_RouteString --
 
249
 *
 
250
 *     Get a string for the given route.
 
251
 *
 
252
 *  Result:
 
253
 *     A string representing the route, if the route is valid, otherwise an
 
254
 *     empty string.
 
255
 *
 
256
 *  Side effects:
 
257
 *     None.
 
258
 *
 
259
 *------------------------------------------------------------------------------
 
260
 */
 
261
 
 
262
const char *
 
263
VMCI_RouteString(VMCIRoute route) // IN
 
264
{
 
265
   const char *vmciRouteStrings[] = {
 
266
      "none",
 
267
      "as host",
 
268
      "as guest",
 
269
   };
 
270
   if (route >= VMCI_ROUTE_NONE && route <= VMCI_ROUTE_AS_GUEST) {
 
271
      return vmciRouteStrings[route];
 
272
   }
 
273
   return "";
 
274
}